1Spring自动装配的分类
Spring能自动装配Bean与Bean之间的依赖关系,即无须使用ref显式地指定依赖Bean,而是由Spring容器检查XML配置文件内容。根据某种规则,为调用者Bean注入被依赖的Bean。
Spring的自动装配可以通过<beans../>元素的default-autowire属性指定,该属性对配置文件中所有的Bean起作用;也可以通过<bean>元素的autowire属性指定,该属性只对当前bean起作用。
自动装配可以减少配置文件的工作量,但是降低了依赖关系的透明性和确定性。
自动装配分为如下几种类型:
- no :不使用自动装配。Bean依赖关系完全由ref元素定义。这是默认的配置,在较大的部署环境中不鼓励改变这个配置,显示配置合作者能够得到更清晰的关系。
- byName:根据setter名字进行自动装配。Spring容器查找容器中的全部Bean,找出其id与setter方法名去掉set前缀,并小写首字母后同名的Bean来完成注入。如果没有找到匹配的Bean实例,不会进行注入。
- byType:根据setter方法的形参类型来自动装配。Spring容器查找容器中的全部Bean,如果有一个Bean类型与setter类型匹配,就自动注入这个Bean,如果找到多个,就抛出异常;如果没有找到,不会发生注入。
- constructor:与byType类似,区别是用于自动匹配构造器的参数。如果容器找不到适配的构造器,抛出一个异常
- autodect:Spring容器根据Bean内部结构,自定决定使用constructor或byType策略。如果找到一个默认的构造函数,那么就会应用byType策略。
2 byName
定义两个类,A,B,A类中包含一个setXiaoB()方法,spring配置文件中定义一个id为xiaoB的Bean,Spring会为其自动注入
(1) 类 A,B
class A
{
private B xiaoB;
public void setXiaoB(B xiaoB)
{
System.out.println("A注入B");
this.xiaoB = xiaoB;
}
}
class B
{
}
(2) 配置文件
<bean id="xiaoA" class="com.songxu.autowire.A" autowire="byName">
</bean>
<bean id="xiaoB" class="com.songxu.autowire.B" >
</bean>
结果注入成功,对于这种注入来说,Spring仅仅会根据名字去查找,即使类型不匹配也会发生注入,只是在注入的时候抛出类型转换异常。
3 byType
还是利用上面的A,B类,仅仅修改一下配置文件
<bean id="xiaoA" class="com.songxu.autowire.A" autowire="byType">
</bean>
<bean id="B" class="com.songxu.autowire.B" >
</bean>
这时spring将自动完成byType的注入。如果同时定义了多个B类型的Bean的话,就会抛出No unique bean of type [com.songxu.autowire.B] is defined:异常。对于这种情况的解决,可以设置autowire-candidate属性,设置autowire-candidate="false",即可将该bean排除在autowire之外。
4 constructor
这种方法不是很常用。定义A类,并利用构造方法初始化属性xiaoB。
class A
{
private B xiaoB;
public void setXiaoB(B xiaoB)
{
System.out.println("A注入B");
this.xiaoB = xiaoB;
}
public A(B xiaoB)
{
System.out.println("构造xiaoB");
this.xiaoB=xiaoB;
}
public A()
{
System.out.println("默认构造A");
}
}
class B
{
}
配置文件
<bean id="xiaoA" class="com.songxu.autowire.A" autowire="constructor">
</bean>
<bean id="B" class="com.songxu.autowire.B" >
</bean>
这个时候在A初始化的时候,将把xiaoB通过构造方法自动注入。这里需要注意的时候,它是一种依照类型查找的方式,如果在配置文件中定义了多个B类型的Bean,将不会触发这种注入方式,而是使用默认的构造方法构造A对象。
对于上面介绍的三种方式,如果指定了ref属性,那么所有自动装配都将失效。
5 集合的自动装配
对于数组和集合类型的自动装配,仅能自动装配接口类型,而不能是他们的实现类。对于这个原因,可参考这篇博客。
下面一个例子
(1)Bean的定义
public class A
{
//private B xiaoB;
private List<B> list;
/*private B getXiaoB()
{
return xiaoB;
}
public void setXiaoB(B xiaoB)
{
System.out.println("xiaoB注入 ");
this.xiaoB = xiaoB;
}*/
public List<B> getList()
{
return list;
}
//此处设置 list 与ArrayList是有区别的
public void setList(List<B> list)
{
this.list = list;
}
}
(2)配置文件
<bean id="xiaoA" class="com.songxu.autowire.A" autowire="byType">
</bean>
<bean id="xiaoB" class="com.songxu.autowire.B" ></bean>
<bean id="xiaoB2" class="com.songxu.autowire.B" ></bean>
<bean id="xiaoB3" class="com.songxu.autowire.B" ></bean>
<bean id="xiaoB4" class="com.songxu.autowire.B" ></bean>
<bean id="xiaoB5" class="com.songxu.autowire.B" ></bean>
<bean id="xiaoB6" class="com.songxu.autowire.B" ></bean>
<bean id="xiaoB7" class="com.songxu.autowire.B" ></bean>