Spring 属性注入

1. 案例环境

1.1. 依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>

1.2. 编写Bean

1
2
3
4
5
6
7
8
9
package bean;

import lombok.Data;

@Data
public class Car {
private String name;
private Double price;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package bean;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import lombok.Data;

@Data
public class Person {
private String name;
private Integer age;
private Object[] arr;
private int[] intArr;
private List<Object> list;
private Set<Object> set;
private Map<Object, Object> map;
private Properties prop;
private Car car1;
private Car car2;
public Person() {
System.out.println("person");
}
public Person(String name) {
System.out.println(name);
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
System.out.println("Person(String name, Integer age)");
}

public Person(Integer age, String name) {
this.name = name;
this.age = age;
System.out.println("Person(Integer age, String name)");
}
}

2. 通过property标签注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<bean id="car" class="bean.Car">
<property name="name" value="car" />
<property name="price" value="5000.0" />
</bean>

<bean id="person" class="bean.Person">
<property name="name" value="foo" />
<property name="age" value="10" />
<property name="arr">
<array>
<!-- 元素类型是Object,不指定type,设置类型是字符串,所以这里的10是字符串,而不 是数字 -->
<value>10</value>
<value type="int">100</value>
<value type="double">3.14</value>
<value>默认是字符串类型</value>
<value type="java.lang.Integer">200</value>
<value type="java.lang.String">字符串</value>
<!-- 引用外部Bean -->
<ref bean="car" />
<!-- 引用内部Bean -->
<bean class="bean.Car">
<property name="name" value="Santana"/>
</bean>
</array>
</property>
<property name="intArr">
<!-- 容器元素类型是int,所以不必设置type属性 -->
<array>
<value>1</value>
<value>2</value>
</array>
</property>
<property name="list">
<list>
<value type="int">100</value>
<value type="double">3.14</value>
<value>默认是字符串类型</value>
<value type="java.lang.Integer">200</value>
<value type="java.lang.String">字符串</value>
<ref bean="car" />
</list>
</property>
<property name="set">
<set>
<value type="int">100</value>
<value type="double">3.14</value>
<value>默认是字符串类型</value>
<value type="java.lang.Integer">200</value>
<value type="java.lang.String">字符串</value>
<ref bean="car" />
</set>
</property>
<property name="map">
<!-- map = new LinkedHashMap<>() -->
<map>
<entry key="key1默认是字符串" value="value默认是字符串" />
<entry key="key2" value="100" value-type="int" />
<entry key="key3" value="100" value-type="java.lang.Integer" />
<entry key="key4">
<array>
<value type="int">10</value>
<value type="java.lang.String">10</value>
</array>
</entry>
<entry key="key5">
<bean class="bean.Car">
<property name="name" value="hehe" />
<property name="price" value="100.0" />
</bean>
</entry>
<entry key-ref="car" value="111" />
<entry key="car" value-ref="car" />
<entry key-ref="car" value-ref="car" />
</map>
</property>
<property name="prop">
<props>
<prop key="aaa">111</prop>
<prop key="bbb">222</prop>
</props>
</property>
<property name="car1" ref="car" />
<property name="car2">
<bean class="bean.Car">
<property name="name" value="haha" />
<property name="price" value="100.0" />
</bean>
</property>
</bean>

3. 属性类型声明

3.1. value标签的type属性

关于数组、集合等容器元素的声明:

  • 如果容器元素类型是Object,则使用value标签为元素赋值时,有必要指定type属性。若不指定,默认是String
  • 如果容器元素类型不是Object,则不必使用type属性。Spring会自动判断类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<property name="arr">
<array>
<!-- 元素类型是Object,不指定type,设置类型是字符串,所以这里的10是字符串,而不 是数字 -->
<value>10</value>
<value type="int">100</value>
<value type="double">3.14</value>
<value>默认是字符串类型</value>
<value type="java.lang.Integer">200</value>
<value type="java.lang.String">字符串</value>
<ref bean="car" />
</array>
</property>
<property name="intArr">
<!-- 容器元素类型是int,所以不必设置type属性 -->
<array>
<value>1</value>
<value>2</value>
</array>
</property>

3.2. 容器标签的key-type / value-type属性

array、list、set、props标签都有value-type属性,用来声明元素的类型

1
2
3
4
5
6
<!-- value-type: 统一声明数组元素的类型 -->
<array value-type="int">
<value>100</value>
<value>200</value>
<value>#{200 + 300}</value>
</array>

map可以声明key-type和value-type

1
2
3
4
<map key-type="int" value-type="java.lang.String">
<entry key="111" value="aaa" />
<entry key="222" value="bbb" />
</map>

4. null空引用注入

错误示例:value设置为”null”,这是字符串,而不是空引用

1
2
3
4
5
<bean id="car" class="bean.Car">
<!-- 字符串"null" -->
<property name="name" value="null"/>
<property name="price" value="5000.0" />
</bean>

正确示例:

1
2
3
4
5
6
<bean id="car" class="bean.Car">
<property name="name">
<null />
</property>
<property name="price" value="5000.0" />
</bean>

5. 有参构造方法注入

5.1. 方式1:constructor-arg指定name/value(最常用)

1
2
3
4
5
<bean id="person" class="bean.Person">
<!-- 匹配Person(String name, Integer age), name=10, age=20 -->
<constructor-arg name="name" value="10" />
<constructor-arg name="age" value="20" />
</bean>

5.2. 方式2:constructor-arg只指定value

1
2
3
4
5
<bean id="person" class="bean.Person">
<!-- 匹配Person(String name, Integer age), name=10, age=20 -->
<constructor-arg value="10" />
<constructor-arg value="20" />
</bean>

5.3. 方式3: constructor-arg指定value和type

1
2
3
4
5
<bean id="person" class="bean.Person">
<!-- 匹配Person(String name, Integer age), name=20, age=10 -->
<constructor-arg value="10" type="java.lang.Integer" />
<constructor-arg value="20" type="java.lang.String" />
</bean>

5.4. 方式4: constructor-arg指定index

1
2
3
4
5
<bean id="person" class="bean.Person">
<!-- 匹配Person(Integer age, String name), name=20, age=10 -->
<constructor-arg value="10" type="java.lang.Integer" index="0" />
<constructor-arg value="20" type="java.lang.String" index="1" />
</bean>

6. ref引用外部Bean组件

1
2
3
4
5
6
7
8
9
<bean id="car" class="bean.Car">
<property name="name" value="benz" />
<property name="price" value="5000.0" />
</bean>

<bean id="person" class="bean.Person">
<!-- 引用car组件 -->
<property name="car1" ref="car" />
</bean>

编写测试方法,可以看到person的car1其实就是car组件,car1并没有创建新的对象

1
2
3
4
5
6
7
8
@Test
public void testIoc() throws Exception {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = ioc.getBean("person", Person.class);
Car car = ioc.getBean(Car.class);
// 输出true。说明两个引用指向同一对象
System.out.println(person.getCar1() == car);
}

7. 引用内部Bean组件

1
2
3
4
5
6
7
8
9
<bean id="person" class="bean.Person">
<property name="car1">
<!-- 内部再创建一个Bean组件,与外部的car是不同的对象 -->
<bean id="car1" class="bean.Car">
<property name="name" value="benz" />
<property name="price" value="5000.0" />
</bean>
</property>
</bean>
panchaoxin wechat
关注我的公众号
支持一下