1.属性注入
属性注入即通过setXxxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。
属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化对象,然后通过反射的方式调用Setter方法注入属性值。
1 | public class Cat { |
Cat类中定义了3个属性,并分别提供了对应的Setter方法和默认构造函数。
配置文件中对cat进行属性注入
1 | <?xml version="1.0" encoding="UTF-8"?> |
测试
1 | public class test { |
输出:
PS:Spring只会检查Bean中是否有对应的Setter方法,至于Bean中是否有对应的属性变量则不做要求。如上面。
2.构造函数注入
构造函数注入是除属性注入之外的另一种常用的注入方式,它保证一些必要的属性在Bean实例化时就得到设置,并且确保了Bean实例在实例化后就可以使用。
按类型匹配入参
如此构造函数:
1
2
3
4public Cat(String name,double price){
this.name=name;
this.price=price;
}配置:
1
2
3
4<bean id="c3" class="com.smart.model.Cat">
<constructor-arg type="java.lang.String" value="旺财"/>
<constructor-arg type="double" value="20"/>
</bean>
按索引匹配入参
如此构造函数:第二个和第三个都是int类型
1
2
3
4
5public Cat(String color, int age, int weigth) {
this.color = color;
this.age = age;
this.weigth = weigth;
}配置:
1
2
3
4
5<bean id="c4" class="com.smart.model.Cat">
<constructor-arg index="0" value="紫色"/>
<constructor-arg index="1" value="4"/>
<constructor-arg index="2" value="30"/>
</bean>
联合使用类型和索引匹配入参
如下面两个构造函数:需要联合使用type和index才能确定配置项和构造函数入参的对应关系。
1
2
3
4
5
6
7
8
9
10public Cat(String color, int age, int weigth) {
this.color = color;
this.age = age;
this.weigth = weigth;
}
public Cat(String color, int age, double price) {
this.color = color;
this.age = age;
this.price = price;
}配置:配置第二个构造函数
1
2
3
4
5<bean id="c5" class="com.smart.model.Cat">
<constructor-arg index="0" type="java.lang.String" value="蓝色"/>
<constructor-arg index="1" type="int" value="3"/>
<constructor-arg index="2" type="double" value="600"/>
</bean>
通过自身类型反射匹配入参
如果Bean构造函数入参的类型是可辨别的(其他的Bean),由于Java反射机制可以获取构造函数入参的类型,即使构造函数注入的配置不提供类型和索引的信息,Spring依旧可以正确地完成构造函数的注入工作。
如下面People类的构造函数:
1
2
3
4
5
6public People(String name, int age, Cat c, Dog d) {
this.name = name;
this.age = age;
this.c = c;
this.d = d;
}配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16<bean id="p" class="com.smart.model.People">
<constructor-arg value="老GS"/>
<constructor-arg value="21"/>
<constructor-arg ref="d4"/>//引用其他Bean
<constructor-arg ref="c4"/>//引用其他Bean
</bean>
<bean id="c4" class="com.smart.model.Cat"
p:weigth="40"
p:color="橘色"
p:age="2"
/>
<bean id="d4" class="com.smart.model.Dog"
p:weigth="30"
p:color="白色"
p:age="3"
/>执行:
1
2People p1=cxt.getBean("p", People.class);
System.out.println(p1.getName()+" "+p1.getC().getColor()+" "+p1.getD().getColor());**输出: ** 老GS 橘色 白色
注入集合类型属性
List
为People添加一个List类型的hobby属性并添加setter。
1
2
3
4private List favorites=new ArrayList();
public void setFavorites(List favorites) {
this.favorites = favorites;
}Xml:
1
2
3
4
5
6
7
8
9
10<bean id="p2" class="com.smart.model.People">
<property name="favorites">
<list>
<value>rap</value>
<value>唱</value>
<value>跳</value>
<value>打篮球</value>
</list>
</property>
</bean>执行:
1
2People p2=cxt.getBean("p2", People.class);
System.out.println(p2.getFavorites());输出:rap, 唱, 跳, 打篮球
List属性既可以通过< value >出入字符串,也可以通过< ref >注入容器中的其他Bean。
Map
为People添加一个Map类型的work属性并添加setter:
1
2
3
4
5private Map work=new HashMap();
public void setWork(Map work) {
this.work = work;
}Xml
1
2
3
4
5
6
7
8<bean id="p3" class="com.smart.model.People">
<property name="work">
<map>
<entry key="9点" value="上课"/>
<entry key="18点" value="放学"/>
</map>
</property>
</bean>执行
1
2People p2=cxt.getBean("p3", People.class);
System.out.println(p2.getWork());输出:9点=上课, 18点=放学
假如某一Map元素的键和值都是对象,则采取以下配置:
1
2
3
4<entry>
<key><ref bean="keyBean"></ref></key>
<ref bean="valueBean"></ref>
</entry>
通过util命名空间配置集合类型的Bean
如果希望配置一个集合类型的Bean,而非一个集合类型的属性,则可以通过util命名空间进行配置。
Xml
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<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"//引入util命名空间
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util //util:list声明
http://www.springframework.org/schema/util/spring-util.xsd //util:list声明
">
<util:list id="list1" list-class="java.util.LinkedList">
<value>看电视</value>
<value>玩游戏</value>
<value>运动</value>
</util:list>
<util:set id="set1">
<value>看电视</value>
<value>玩游戏</value>
<value>运动</value>
</util:set>
<util:map id="map1">
<entry key="9点" value="吃饭"/>
<entry key="18点" value="吃晚饭"/>
</util:map>
</beans>测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class test3 {
public static void main(String[] args) {
ApplicationContext cxt=new ClassPathXmlApplicationContext("beans/util.xml");
List list=cxt.getBean("list1",java.util.LinkedList.class);
Set set=cxt.getBean("set1",java.util.Set.class);
Map map=cxt.getBean("map1",java.util.Map.class);
System.out.println(list+" "+set+" "+map);
}
}输出: [看电视, 玩游戏, 运动] [看电视, 玩游戏, 运动] {9点=吃饭, 18点=吃晚饭}
自动装配
< bean >元素提供了一个指定自动装配类型的属性:**autowire=”<自动装配类型>”**。Spring提供了4种自动装配类型。
byName
根据名称进行自动匹配。假设People有一个名为cat的属性,如果容器中刚好有一个名为car的Bean,Spring就会自动将其装配给People的cat属性。
byType
根据类型进行自动匹配。假设People有一个名为cat的属性,如果容器中刚好有一个Cat类型的Bean,Spring就会自动将其装配给People的cat属性。
constructor
与byType类似,只不过它是针对构造函数注入而言的,假设People有一个构造函数,构造函数包含一个Cat类型的入参,如果容器中有一个Cat类型的Bean,则Spring将自动把这个Bean作为People构造函数的入参,如果容器中没有找到和构造函数入参匹配类型的Bean,Spring抛出异常。
autodetect
根据Bean的自省机制决定采用byType还是constructor进行自动装配:如果Bean提供了默认的构造函数,则采用byType;否则采用constructor。
如将上面id=”p”的Bean改为:
1 | <bean id="p" class="com.smart.model.People" |
执行:
1 | People p1=cxt.getBean("p", People.class); |
**输出: **老GS 橘色 白色
可见,容器自动将c4、d4注入了。