简单理解
自动装配,就是将一个Bean注入到其他Bean的Property中。Spring框架式默认不支持自动装配的,要想使用自动装配需要修改spring配置文件中<bean>标签的autowire属性
代码样例
package com.spring.auto.autowire;
public class Cat {
public void sayCat(){
System.out.println("猫叫");
}
}
package com.spring.auto.autowire;
public class Dog {
public void sayDog(){
System.out.println("狗叫");
}
}
package com.spring.auto.autowire;
public class Person {
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public String getSay() {
return say;
}
public void setSay(String say) {
this.say = say;
}
private Dog dog;
private Cat cat;
private String say;
}
package com.spring.auto.autowire;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/spring/auto/autowire/spring_autowire.xml");
Person person = (Person) applicationContext.getBean("test");
person.getCat().sayCat();
person.getDog().sayDog();
System.out.println(person.getSay());
}
}
五种自动装配模式
1、no
该模式表示默认情况下,不自动装配,通过“ref”attribute手动设定。
例如:
<bean id="cat_c" class="com.spring.auto.autowire.Cat"></bean>
<bean id="dog_d" class="com.spring.auto.autowire.Dog"></bean>
<bean id="test" class="com.spring.auto.autowire.Person">
<property name="cat" ref="cat_c"/>
<property name="dog" ref="dog_d"/>
<property name="say" value="测试"/>
</bean>
2、byName
该模式表示根据Property的Name自动装配,如果一个bean的name,和另一个bean中的Property的name相同,则自动装配这个bean到Property中。当一个bean节点带有 autowire byName的属性时,将查找其类中所有的set方法名,获得将set去掉并且首字母小写的字符串,然后去spring容器中寻找是否有此字符串名称id的对象。如果有,就取出注入;如果没有,就报空指针异常。
例如:
<bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
<bean id="dog" class="com.spring.auto.autowire.Dog"></bean>
<bean id="test" class="com.spring.auto.autowire.Person" autowire="byName">
<property name="say" value="测试"/>
</bean>
如果将如果将bean id="cat'的值改成bean id="catname",执行时报空指针Exception in thread "main" java.lang.NullPointerException at com.spring.auto.autowire.Test.main(Test.java:11)。因为按byName规则找不对应set方法,真正的setCat就没执行,对象就没有初始化,所以调用时就会报空指针错误。
3、byType
该模式表示根据Property的数据类型(Type)自动装配,Spring会总动寻找与属性类型相同的bean,若一个bean的数据类型,兼容另一个bean中Property的数据类型,则自动装配。
注意:使用byType首先需要保证同一类型的对象,在spring容器中唯一,若不唯一会报不唯一的异常。
例如:
<bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
<bean id="dog" class="com.spring.auto.autowire.Dog"></bean>
<bean id="test" class="com.spring.auto.autowire.Person" autowire="byType">
<property name="say" value="测试"/>
</bean>
若配置文件中有两个类型相同的bean
<bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
<bean id="cat_c" class="com.spring.auto.autowire.Cat"></bean>
一旦配置如上,有两种相同数据类型的bean被配置,将抛出UnsatisfiedDependencyException异常:警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'test' defined in class path resource [com/spring/auto/autowire/spring_autowire.xml]: Unsatisfied dependency expressed through bean property 'cat'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.spring.auto.autowire.Cat' available: expected single matching bean but found 2: cat,cat_c
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'test' defined in class path resource [com/spring/auto/autowire/spring_autowire.xml]: Unsatisfied dependency expressed through bean property 'cat'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.spring.auto.autowire.Cat' available: expected single matching bean but found 2: cat,cat_c
所以,一旦选择了’byType’类型的自动装配,必须确认配置文件中每个数据类型定义一个唯一的bean。
4、constructor
使用构造方法完成对象注入,其实也是根据构造方法的参数类型进行对象查找,相当于采用byType的方式。即Spring会寻找与参数数据类型相同的bean,通过构造函数将其注入。
例如:
<bean id="cat" class="com.spring.auto.autowire.Cat"></bean>
<bean id="dog" class="com.spring.auto.autowire.Dog"></bean>
<bean id="test" class="com.spring.auto.autowire.Person" autowire="constructor">
<constructor-arg index="2" value="55"></constructor-arg>
</bean>
5、default
表示默认采用上一级标签的自动装配的取值。如果存在多个配置文件的话,那么每一个配置文件的自动装配方式都是独立的。
XML 配置里的 Bean 自动装配的缺点
1、在 Bean 配置文件里设置 autowire 属性进行自动装配将会装配 Bean 的所有属性,然而,,若只希望装配个别属性时, autowire 属性就不够灵活了。
2、autowire 属性要么根据类型自动装配, 要么根据名称自动装配, 不能两者兼而有之。
3、一般情况下,在实际的项目中很少使用自动装配功能,因为和自动装配功能所带来的好处比起来,明确清晰的配置文档更有说服力一些。