13--Spring 构造函数注入和Setter方法注入及集合注入(一)


新版连接 01–Spring源码深度解析目录


上一篇我们介绍了BeanFactory和FactoryBean的区别,接下来我们再来分析一下Spring依赖注入的方式,Spring的依赖注入方式大体上可以分为三种:

  • 构造函数注入
  • Setter方法注入
  • 方法注入 (lookup-method注入和replace-method注入)

本篇我们先分析构造函数注入和Setter方法注入,并简介一下Spring中的集合属性,Properties属性,数组属性等注入,方法注入稍微复杂且不常用,我们留在下篇分析。

1. 构造函数注入
  • 新建HelloApi接口
package com.lyc.cn.day04;

/**
 * @author: LiYanChao
 * @create: 2018-09-05 11:49
 */
public interface HelloApi {

	void sayHello();

	void sayListNames();

	void saySetNames();

	void sayArrayNames();

	void sayMapNames();

	void sayPropertiesNames();
}
  • 新建HelloImpl实现类
package com.lyc.cn.day04;

import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @author: LiYanChao
 * @create: 2018-09-05 11:49
 */
public class HelloImpl implements HelloApi {

	/** 姓名 **/
	private String name;

	/** 年龄 **/
	private int age;

	/** 注入List集合 **/
	private List<String> listNames;

	/***注入Set集合*/
	private Set<String> setNames;

	/** 注入Properties **/
	private Properties propertiesNames;

	/** 注入Map集合 **/
	private Map<String, String> mapNames;

	/** 注入数组 **/
	private String[] arrayNames;

	/** 无参构造函数 **/
	public HelloImpl() {

	}

	/**
	 * 构造函数
	 * @param name 姓名
	 * @param age  年龄
	 */
	public HelloImpl(String name, int age) {
		this.name = name;
		this.age = age;
	}

	/**
	 * 打印数组集合
	 */
	public void sayArrayNames() {
		System.out.println("注入数组-->");
		if (arrayNames != null && arrayNames.length > 0) {
			for (int i = 0; i < arrayNames.length; i++) {
				System.out.println(arrayNames[i]);
			}
		}
		System.out.println();
	}

	/**
	 * 打印Map集合
	 */
	public void sayMapNames() {
		if (null != mapNames && mapNames.size() > 0) {
			System.out.println("注入Map集合-->");
			for (Map.Entry<String, String> entry : mapNames.entrySet()) {
				System.out.println("key= " + entry.getKey() + " value= " + entry.getValue());
			}
			System.out.println();
		}
	}

	/**
	 * 打印Properties属性
	 */
	public void sayPropertiesNames() {
		if (null != propertiesNames) {
			System.out.println("注入properties属性-->");
			System.out.println(propertiesNames.get("name"));
			System.out.println(propertiesNames.get("age"));
			System.out.println();
		}
	}

	/**
	 * 打印List集合
	 */
	public void sayListNames() {
		if (!CollectionUtils.isEmpty(listNames)) {
			System.out.println("注入List集合-->");
			for (String string : listNames) {
				System.out.println(string);
			}
			System.out.println();
		}
	}

	/**
	 * 打印Set集合
	 */
	public void saySetNames() {
		if (!CollectionUtils.isEmpty(setNames)) {
			System.out.println("注入Set集合-->");
			Iterator<String> iterator = setNames.iterator();
			while (iterator.hasNext()) {
				System.out.println(iterator.next());
			}
			System.out.println();
		}
	}

	@Override
	public void sayHello() {
		System.out.println("大家好, 我叫" + getName() + ", 我今年" + getAge() + "岁了");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public List<String> getListNames() {
		return listNames;
	}

	public void setListNames(List<String> listNames) {
		this.listNames = listNames;
	}

	public Set<String> getSetNames() {
		return setNames;
	}

	public void setSetNames(Set<String> setNames) {
		this.setNames = setNames;
	}

	public Properties getPropertiesNames() {
		return propertiesNames;
	}

	public void setPropertiesNames(Properties propertiesNames) {
		this.propertiesNames = propertiesNames;
	}

	public Map<String, String> getMapNames() {
		return mapNames;
	}

	public void setMapNames(Map<String, String> mapNames) {
		this.mapNames = mapNames;
	}

	public String[] getArrayNames() {
		return arrayNames;
	}

	public void setArrayNames(String[] arrayNames) {
		this.arrayNames = arrayNames;
	}
}
  • 新建day04.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!-- ====================构造器属性注入(静态工厂和实例工厂属性注入方式与构造器方式注入相同)Begin==================== -->
	<!-- 通过构造器参数索引方式依赖注入 -->
	<bean id="helloBeanByIndex" class="com.lyc.cn.day04.HelloImpl">
		<constructor-arg index="0" value="小张"/>
		<constructor-arg index="1" value="3"/>
	</bean>
	<!-- 通过构造器参数类型方式依赖注入 -->
	<bean id="helloBeanByType" class="com.lyc.cn.day04.HelloImpl">
		<constructor-arg type="java.lang.String" value="小李"/>
		<constructor-arg type="int" value="4"/>
	</bean>
	<!-- 通过构造器参数名称方式依赖注入 -->
	<bean id="helloBeanByName" class="com.lyc.cn.day04.HelloImpl">
		<constructor-arg name="name" value="小王"/>
		<constructor-arg name="age" value="5"/>
	</bean>
	<!-- ====================构造器属性注入End==================== -->
</beans>
  • 新建MyTest测试类
package com.lyc.cn.day04;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

/**
 * @author: LiYanChao
 * @create: 2018-09-05 11:49
 */
public class MyTest {

	private XmlBeanFactory xmlBeanFactory;

	private HelloApi helloApi;

	@Before
	public void initXmlBeanFactory() {
		System.out.println("========测试方法开始=======\n");
		xmlBeanFactory = new XmlBeanFactory(new ClassPathResource("day04.xml"));
	}

	@After
	public void after() {
		System.out.println("\n========测试方法结束=======");
	}

	/**
	 * 构造函数注入
	 */
	@Test
	public void testConstructorDI() {
		helloApi = xmlBeanFactory.getBean("helloBeanByIndex", HelloImpl.class);
		helloApi.sayHello();

		helloApi = xmlBeanFactory.getBean("helloBeanByType", HelloImpl.class);
		helloApi.sayHello();

		helloApi = xmlBeanFactory.getBean("helloBeanByName", HelloImpl.class);
		helloApi.sayHello();
	}
}
  • 输出
========测试方法开始=======

大家好, 我叫小张, 我今年3岁了
大家好, 我叫小李, 我今年4岁了
大家好, 我叫小王, 我今年5岁了

========测试方法结束=======

可以看到,构造函数也分为了三种类型指定参数索引指定参数类型指定参数名称三种方式,当我们指定任意一种方式时,Spring会自动帮我们识别对应的构造函数,并将值进行注入,这一部分的实现在Spring源码中的实现还是很复杂的,会在接下来的博客中进行详细分析。

2. Setter方法注入

Setter方法注入是最简单也是最基础的一种注入方式,在本小节我们会分析普通属性注入数组属性注入List属性注入Map类型属性注入Properties类型属性注入等方式

  • 修改day04.xml增加bean配置信息
<!-- ====================Setter方法属性注入Begin==================== -->
<bean id="helloBeanBySetter" class="com.lyc.cn.day04.HelloImpl">
	<property name="name" value="小明"/>
	<property name="age" value="3"/>
</bean>

<bean id="helloBeanBySetterCollection" class="com.lyc.cn.day04.HelloImpl">
	<!--注入List集合-->
	<property name="listNames">
		<!-- merge 父子bean是否合并条目 -->
		<list value-type="java.lang.String" merge="false">
			<value>张三</value>
			<value>李四</value>
			<value>王五</value>
		</list>
	</property>

	<!--注入Set集合-->
	<property name="setNames">
		<set value-type="java.lang.String" merge="true">
			<value>张三</value>
			<value>李四</value>
			<value>王五</value>
		</set>
	</property>

	<!--注入Map集合-->
	<property name="mapNames">
		<map key-type="java.lang.String" value-type="java.lang.String">
			<entry key="name" value="小明"/>
			<entry key="age" value="3"/>
		</map>
	</property>

	<!--注入数组-->
	<property name="arrayNames">
		<array value-type="java.lang.String">
			<value>张三</value>
			<value>李四</value>
			<value>王五</value>
		</array>
	</property>

	<!--注入Properties-->
	<property name="propertiesNames">
		<props value-type="java.lang.String">
			<prop key="name">小明</prop>
			<prop key="age">3</prop>
		</props>
	</property>
</bean>
<!-- ====================Setter方法属性注入End==================== -->
  • 修改MyTest类增加测试用例
/**
 * setter方法注入
 */
@Test
public void testSetterDI() {
	helloApi = xmlBeanFactory.getBean("helloBeanBySetter", HelloImpl.class);
	System.out.println("注入单个属性-->");
	helloApi.sayHello();
	System.out.println("");

	helloApi = xmlBeanFactory.getBean("helloBeanBySetterCollection", HelloImpl.class);
	helloApi.sayListNames();
	helloApi.saySetNames();
	helloApi.sayArrayNames();
	helloApi.sayMapNames();
	helloApi.sayPropertiesNames();
}
  • 输出
========测试方法开始=======

注入单个属性-->
大家好, 我叫小明, 我今年3岁了

注入List集合-->
张三
李四
王五

注入Set集合-->
张三
李四
王五

注入数组-->
张三
李四
王五

注入Map集合-->
key= name value= 小明
key= age value= 3

注入properties属性-->
小明
3

========测试方法结束=======

对于构造器和Setter方法注入就先分析到这里,都是一些配置上的操作,比较简单,在开发中也比较实用,再下一个小节中会分析方法注入(lookup-method注入和replace-method注入)

方法注入传送:

  • 14–Spring lookup-method注入和replace-method注入(二)

你可能感兴趣的:(Spring5.0源码解析)