前面我们讲Di依赖注入的时候介绍了在xml文件中配置参数注入,Spring 容器可以自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量。
下列自动装配模式,它们可用于指示 Spring 容器为来使用自动装配进行依赖注入。你可以使用 元素的 autowire 属性为一个 bean 定义指定自动装配模式。
Tables | Are |
---|---|
no | 这是默认的设置,它意味着没有自动装配,你应该使用显式的bean引用来连线。你不用为了连线做特殊的事。 |
byName | 由属性名自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byName。然后尝试匹配,并且将它的属性与在配置文件中被定义为相同名称的 beans 的属性进行连接。 |
byType | 由属性数据类型自动装配。Spring 容器看到在 XML 配置文件中 bean 的自动装配的属性设置为 byType。然后如果它的类型匹配配置文件中的一个确切的 bean 名称,它将尝试匹配和连接属性的类型。如果存在不止一个这样的 bean,则一个致命的异常将会被抛出。 |
constructor | 类似于 byType,但该类型适用于构造函数参数类型。如果在容器中没有一个构造函数参数类型的 bean,则一个致命错误将会发生。 |
autodetect | Spring首先尝试通过 constructor 使用自动装配来连接,如果它不执行,Spring 尝试通过 byType 来自动装配。 |
这种模式由属性名称指定自动装配。在 XML 配置文件中 bean 的 auto-wire 属性设置为 byName。然后,它尝试将它的属性与配置文件中定义为相同名称的 bean 进行匹配和连接。如果找到匹配项,它将注入这些 bean,否则,它将抛出异常。
例:
首先创建一个类AutoWiringDAO:
public class AutoWiringDAO {
public void say(String word) {
System.out.println("AutoWiringDAO : " + word);
}
}
然后在创建一个类AutoWiringService持有AutoWiringDAO的实例,并设置set方法:
public class AutoWiringService {
//参数名必须和配置文件中的id一致
private AutoWiringDAO autoWiringDAO;
public void setAutoWiringDAO(AutoWiringDAO autoWiringDAO) {
this.autoWiringDAO = autoWiringDAO;
}
public void say(String word) {
this.autoWiringDAO.say(word);
}
}
按照之前的操作,我们要这样修改配置文件:
<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.xsd">
<bean id="autoWiringService" class="com.mss.test.AutoWiringService">
<property name="autoWiringDAO" ref="autoWiringDAO" />
bean>
//id必须和类文件中的参数名一样
<bean id="autoWiringDAO" class="com.mss.test.AutoWiringDAO">bean>
beans>
如果使用byName要怎样操作呢:
<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.xsd">
<bean id="autoWiringService" class="com.mss.test.AutoWiringService" autowire="byName">bean>
<bean id="autoWiringDAO" class="com.mss.test.AutoWiringDAO">bean>
beans>
我们测试一下:
@RunWith(BlockJUnit4ClassRunner.class)
public class TestOneInterface extends UnitTestBase{
public TestOneInterface() {
super("classpath*:spring-ioc.xml");
}
@Test
public void testAutoWriter() {
AutoWiringService autoWiringService=super.getBean("autoWiringService");
autoWiringService.say("hello");
}
}
输出结果:
AutoWiringDAO : hello
我们知道byName是类中的参数和配置文件中id定义为相同名称的 bean 进行匹配和连接,他的限制就是参数名必须和bean中的id一致,而byType不需要,就算bean没有指定id,他依然可以运行。
我们修改一下之前的配置文件:
<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.xsd">
<bean id="autoWiringService" class="com.mss.test.AutoWiringService" autowire="byType">bean>
<bean class="com.mss.test.AutoWiringDAO">bean>
beans>
可以看到我们把autowire的类型修改成了byType,并且把AutoWiringDAO的id删掉,现在运行一下测试类:
AutoWiringDAO : hello
运行结果和原来一样。
这种模式与 byType 非常相似,但它应用于构造器参数。在 XML 配置文件中 bean的 autowire 属性设置为 constructor。然后,它尝试把它的构造函数的参数与配置文件中 bean 名称中的一个进行匹配和连线。如果找到匹配项,它会注入这些 bean,否则,它会抛出异常。
首先在AutoWiringService 中添加构造函数:
public class AutoWiringService {
private AutoWiringDAO autoWiringDAO;
public AutoWiringService(AutoWiringDAO autoWiringDAO) {
this.autoWiringDAO = autoWiringDAO;
}
public void setAutoWiringDAO(AutoWiringDAO autoWiringDAO) {
this.autoWiringDAO = autoWiringDAO;
}
public void say(String word) {
this.autoWiringDAO.say(word);
}
}
如果是手动注入,应该这样修改配置文件:
<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.xsd">
<bean id="autoWiringService" class="com.mss.test.AutoWiringService">
<constructor-arg name="autoWiringDAO" ref="autoWiringDAO">constructor-arg>
bean>
<bean id="autoWiringDAO" class="com.mss.test.AutoWiringDAO">bean>
beans>
现在我们使用自动注入配置:
<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.xsd">
<bean id="autoWiringService" class="com.mss.test.AutoWiringService" autowire="constructor">bean>
<bean class="com.mss.test.AutoWiringDAO">bean>
beans>
可以看到我没有指定id,也就是说他也是根据类型装配。运行结果如下:
AutoWiringDAO : hello
上面我们指定装配方式都是在bean结点下指定的,这样只在当前bean中有效,可不可以配置全局有效呢?当然是可以的了,我们只需要在beans结点中配置default-autowire属性即可。但是他的优先级是没有autowire高的,也就说如果我在bean结点下配置了autowire属性,即使在beans结点中配置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.xsd"
default-autowire="byName">
beans>