首先我们来看一下以前我们是如何手动装配一个bean的:
先看一段java程序:
public class Customer
{
private Person person;
public void setPerson(Person person) {
this.person = person;
}
}
public class Person {……}
这时在配置文件当中默认autowire属性值为:no,即不使用默认装配,这时只有通过<ref>标签手动装配bean
<bean id="customer" class="cn.lovepi.***.Customer">
<property name="person" ref="person" />
</bean>
<bean id="person" class="cn.lovepi.***.Person" />
可以看到:person id的名字和customer bean的person属性的名字是一样的。
具体Spring属性注入请看:Spring学习(十七)Spring 参数注入方式介绍
其实,当Spring装配Bean的属性时,如果非常明确,则可以使用自动装配模式。
Spring提供了4种各具特色的自动装配策略:
- byName:把与bean的属性具有相同名字或者id的其他的bean自动装配到bean对应的属性当中。如果没有跟属性名字相匹配的bean,则该属性不进行装配。
- byType:把与bean的属性具有相同类型的其他bean自动装配到bean的对应属性当中。如果没有跟属性类型的bean,则属性不被装配。
- constructor:把与bean的构造函数入参具有相同类型的其他bean自动装配到bean的构造器对应的入参当中。
- autodetect:首先先将尝试使用constructor进行自动装配,如果失败,则尝试使用byType进行自动装配。
接下来详细的了解下这四种装配方式的优缺点。
1.byName:为属性自动装配与该属性名字相同的bean
在Spring当中,所有的东西都会被赋予一个名字。因此,bean的属性也会有一个名字。就像装配进属性的bean一样,假如属性的名字恰好与该属性的bean的名字一样,那么只要配置了autowire属性,Spring便会自动将这个bean装配到属性当中去。
如下所示:
<bean id="customer" class="cn.lovepi.***.Customer” autowire="byName" />
<bean id="person" class="cn.lovepi.***.Person" />
2.byType:为属性自动装配与该属性类型相同的bean
<bean id="customer" class="cn.lovepi.***.Customer” autowire="byType" />
<bean id="person" class="cn.lovepi.***.Person" />
当存在多个bean的类型与所要装配的属性类型相同的时候,Spring会抛出异常。
为了避免使用byType自动装配而带来的歧义,Spring为我们提供了两种解决方法:
- 可以为自动装配标志一个首选bean,使用primary属性,属性的默认值为true即所有的bean都是首选bean
- 可以取消某个bean自动装配的资格,使用autowire-candidate属性,为false时取消自动装配资格
3.constructor:通过构造器注入来配置bean,取消constructor-arg属性,使用autowire属性设置
<bean id="customer" class="com.jike.***.Customer” autowire=“constructor" />
<bean id="person" class="com.jike.***.Person" />
采用constructor构造器注入bean也具有一定的局限性:
当发现多个bean匹配某个构造器入参的时候,Spring不会去猜测哪一个bean更适合装配。此外,如果一个类有多个构造器,那么他们都满足自动装配的条件的时候,Spring也不会尝试去猜测哪一个构造器更适合使用。
4.autodetect:最佳自动装配策略
<bean id="customer" class="com.jike.***.Customer” autowire=“autodetect" />
<bean id="person" class="com.jike.***.Person" />
首先先将尝试使用constructor进行自动装配,如果失败,则尝试使用byType进行自动装配。
当Spring要为它所创建的所有Bean应用相同的自动装配策略来简化配置时,可以在根元素<bean>上增加一个default-autowire属性:
<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-3.0.xsd”
default-autowire=“byType” >
…………………
</beans>
当我们对某个Bean选择了自动装配策略时,仍然可以为任意一个属性配置<property>属性,即可以同时使用自动装配和显式装配策略:
<bean id="customer" class="com.jike.***.Customer“autowire=“byType" >
<property name="person" ref="person1" />
</bean>
<bean id="person" class="com.jike.***.Person" />
<bean id="person1" class="com.jike.***.Person" />
可以看到我们已经设置了按找类型自动装配bean,但我们也可以显式的使用property属性来加载特定的bean