所谓自动装配,就是将一个Bean注入到其他Bean的Property中,类似于以下:
在beans.xml:
<bean id="user" class="com" autowire=" autowire方式" />
Spring支持5种自动装配模式( autowire方式),如下:
- no ——默认情况下,不自动装配,通过“ref”attribute手动设定。
- buName ——根据Property的Name自动装配,如果一个bean的name,和另一个bean中的Property的name相同,则自动装配这个bean到Property中。
- byType ——根据Property的数据类型(Type)自动装配,如果一个bean的数据类型,兼容另一个bean中Property的数据类型,则自动装配。
- constructor ——根据构造函数参数的数据类型,进行byType模式的自动装配。
- autodetect ——如果发现默认的构造函数,用constructor模式,否则,用byType模式。
实例:
一.目录结构
二.代码
A.java
package com;
public class A {
private B bbb;
private C ccc;
public void setBbb(B bbb) {
this.bbb = bbb;
}
public void setCcc(C ccc) {
this.ccc = ccc;
}
@Override
public String toString() {
bbb.testB();
ccc.testC();
return "我是A对象";
}
}
B.java
package com;
public class B {
public void testB() {
System.out.println("我是B对象");
}
}
C.java
package com;
public class C {
public void testC() {
System.out.println("我是C对象");
}
}
Test.java
package test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.A;
public class Test {
public static void main(String[] args) {
BeanFactory bf=new ClassPathXmlApplicationContext("beans.xml");
A a=(A)bf.getBean("aaa");
System.out.println(a);
}
}
打印结果:
1.当没有autowire:有两种方式的写法
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 方法一:没有autowire的效果 -->
<bean id="aaa" class="com.A">
<property name="bbb"> <bean class="com.B"/></property>
<property name="ccc"> <bean class="com.C"/></property>
</bean>
<!-- 方法二:用ref引用的方式来写,可以写为:
<bean id="aaa" class="com.A" autowire="default">
<property name="bbb" ref="bbb"></property>
<property name="ccc" ref="cccc"></property>
</bean>
<bean id="bbb" class="com.B"></bean>
<bean id="cccc" class="com.C"></bean>
-->
</beans>
2.当autowire="byName" bean的名称和属性名称完全相同
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- autowire="byName",如果 -->
<bean id="aaa" class="com.A" autowire="byName"></bean>
<bean id="bbb" class="com.B"></bean>
<bean id="ccc" class="com.C"></bean>
</beans>
问题:如果根据 ccc name找不到对应的bean配置,如下
<!-- autowire="byName" id的属性必须-->
<bean id="aaa" class="com.A" autowire="byName"></bean>
<bean id="bbb" class="com.B"></bean>
<bean id="ccc123" class="com.C"></bean>
配置文件中找不到ccc,只有ccc123,这时就会装配失败,运行后,A中ccc=null就会出错
3.当autowire="byType"
设置了autowire="byType",Spring会总动寻找与属性类型相同的bean,找到后,通过调用setBbb(B bbb),setCcc(C ccc)将其注入。
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- autowire="byType" id的属性必须-->
<bean id="aaa" class="com.A" autowire="byType"></bean>
<bean id="bbb" class="com.B"></bean>
<bean id="ccc123" class="com.C"></bean>
</beans>
问题:如果配置文件中有两个类型相同的bean会怎样呢?如下:
一旦配置如上,有两种相同数据类型的bean被配置,将抛出UnsatisfiedDependencyException异常,见以下:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException:
所以,一旦选择了’byType’类型的自动装配,请确认你的配置文件中每个数据类型定义一个唯一的bean。
4.当autowire="constructor "
这种情况下,Spring会寻找与参数数据类型相同的bean,通过构造函数public A(B bbb, C ccc)将其注入。
A.java
package com;
public class A {
private B bbb;
private C ccc;
public void setBbb(B bbb) {
this.bbb = bbb;
}
public void setCcc(C ccc) {
this.ccc = ccc;
}
public A(B bbb, C ccc) {
this.bbb = bbb;
this.ccc = ccc;
}
@Override
public String toString() {
bbb.testB();
ccc.testC();
return "我是A对象";
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- autowire="constructor" -->
<bean id="aaa" class="com.A" autowire="constructor"></bean>
<bean id="bbb" class="com.B"></bean>
<bean id="ccc" class="com.C"></bean>
</beans>
5.当autowire="autodetect"
这种情况下,Spring会先寻找A中是否有默认的构造函数,如果有相当于上边的’constructor’这种情况,用构造函数注入,否则,用’byType’这种方式注入,所以,此例中通过调用public A(B bbb, C ccc)将其注入。
<!-- autowire="autodetect" -->
<bean id="aaa" class="com.A" autowire="autodetect"></bean>
<bean id="bbb" class="com.B"></bean>
<bean id="ccc" class="com.C"></bean>
配置文件用手工装配才是最实用的。