天天看点

Spring Bean自动装配

5.6.6 自动装配

Spring 能自动装配bean 与 bean之间的依赖关系,即无须使用 ref显式指定依赖bean,由 BeanFactory 检查 XML 配置文件内容,根据某种规则,为主调 bean 注入依赖关系。自动装配可作为某个 bean 的属性,因此可以指定单独bean,使某些 bean 使用自动装配。自动装配可以减少配置文件的i作量,但降低了依赖关系的透明性和清晰性。

使用 bean 元素的 autowire 属性来配置自动装配,其 autowire 属性可以接受如下值。

no: 不使用自动装配。

       Bean 依赖必须通过 ref元素定义,这是默认的配置,在较大的部署环境中不建议改变这个配置。

byName: 根据属性名自动装配。 BeanFactory 查找容器中全部 bean,并找出其中id 属性与属性同名的 bean 。

byτype: 根据属性类型自动装配。 BeanFacto可查找容器全部 bean,如果恰好有一个与依赖属性类型相同的 bean,就自动装配这个属性:如果有多个这样的 bean,就抛出一个致命异常:如果没有匹配的 bean,则什么都不会发生,因而属性不会被设置:如果需要无法自动装配时抛出异常,设置 dependency-check:"objects"。

construct曰:同 by乃pe 类似,区别是用于构造注入的参数。如果在 BeanFactory中,不是恰好有一个 bean 与构造器参数相同类型,则会产生一个致命的错误。

autodetect:BeanFacto可根据 bean 内部结构,决定使用 constructor 或 byType。如果找到一个默认的构造函数,那么就会应用 byTpe。

1.byName 规则

byName 规则,指通过名字注入依赖关系。假如 beanA 的实现类包含 setter B 方法,而 Spring 的配置文件包含 id 为 b 的 bean。当 Spring 容器为 beanA 注入 b 实例时,如果容器中没有与名字匹配的 bean 时,则抛出异常。看如下配置文件:

<!--XML 文件的文件头部分,指定了 XML 文件的编码集--〉
<?xml version="1.0"encodi口g="gb2312"?>
<!--指定Spring 配置文件的dtd>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"''
http://www.springframework.org/dtd/spring-beans.dtd''>
<!--Spring配置文件的根元素一〉
<beans>
<!-- 指定 chinese bean使用自动装配,按名字装配-->
<bean id="chinese" class="lee.Chinese" autowire = "byName"/>
<!--配置gundogbean 一〉
<bean id="gundog"class="lee.Gundog"><property name="name">
<value>wangwang</value></property>
</bean>
</beans>
      

上面的配置文件,要求Chinese类中有如下方法:

/**
*依赖关系必需的setter方法
*因为需要通过名字自动装配,因此setter方法名
必须是set+ bean 名。 bean 名首字母大写
*@dog 设置的 dog 值
public void setGunDog(Dog dog)
this.dog = dog;
      

2.byType规则

byType 规则,指根据类型匹配来注入依赖关系。假如A 实例有 setB(B b)方法,而Spring配置文件中恰有一个类型B 的 bean 实例,当容器为A 注入类型匹配的bean 实例时,如果容器中没有一个类型为B 的实例,或有多于一个的B 实例时,都将抛出异常。看如下配置文件:

<!--XML文件的文件头部分,指定了XML 文件的编码集>
<?xmlversion="1.0"encoding="gb2312"?>
<!--指定Spring 配置文件的dtd>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<!--Spring配置文件的根元素…〉
<beans>
<!-指定 chinese bean使用自动装配,按名字装配…〉
<bean'id="chinese" class="lee.Chinese" autowire = "byType"/>
<!--配置 gundogbean -->
<bean id="gundog" class="lee.Gundog"><property name="name">
<value>飞Nangwang</value>
</property>
</bean></beans>      

上面的配置文件要求Chinese类中有如下方法:

/**
*依赖关系必需的setter方法
*因为使用按类型自动装配,要求setter方法的参数类型与容器的bean的类型相同。
*程序中的GunDog实现 Dog 接口
*@dog 设置的 dog 值
*/public void setDog(Dog dog)
this.dog= dog;      

但如果出现如下配置文件:

<!--XML 文件的文件头部分,指定了XML 文件的编码集--〉
<?xml version="1.0" encoding="gb2312"?>
<!--指定Spring 配置文件的dtd>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
''http://www.springframework.org/dtd/spring-beans.dtd''>
<!--Spring配置文件的根元素一〉
<beans>
<!--指定 chinese bean使用自动装配,按名字装配…〉
<bean id="chinese" class="lee.Chinese" autowire = "byType"/>
<!-配置 gundogbean 一〉
<bean id="gundog" class="lee.Gundog">
<property name="name">
<value>wangwa口g</value>
</property>
</bean>
<!--配置petdogbean Pegdog也实现Dog接口--〉
<bean id="petdog" class="lee.Petdog"><property name="name">
<value>ohoh</value></property>
</bean></beans>      

此时, Spring将无法按类型自动装配,因为容器中有两个类型为Dog 的 bean,Spring无法确定应为chinesebean注入哪个beano 剩下的两种自动装配大同小异,此处不再赘述。当一个 bean 既使用自动装配依赖,又使用ref显式指定依赖时,则显式指定的依赖将覆盖自动装配。看如下配置文件:

<!--XML文件的文件头部分,指定了XML文件的编码集-->
<?xml version="1.0" encoding="gb2312"?>
<J--指定 Spring 配置文件的dtd>
<lDOCTYPE beans PUBLIC"-//SPRiNG//DTDBEAN//EN"'
'http://www.springframework.org/dtd/spring-beans.dtd''>
<!--Spring配置文件的根元素--〉
<beans><!--指定 chinese bean使用自动装配,按名字装配司〉
<bean id="chinese"class="lee.Chinese" autowire= 
//byName"><property name="Gundog">
<ref local="petdog"/></property>
<!--配置gundogbean -->
<beanid=~gundog"class="lee.Gundog">
<property name="name">
<value>wangwang</value>
</property>
</bean><!--配置petdogbean Pegdog也实现Dog 接口--〉
<bean id="petdog" class="lee.petdog">
<property name="name">
<value>ohoh</value>
</property>
</bean>
</beans>      

可以看出,即使Chinese 类中有 setGundog(Dog dog)方法, Spring依然注入petdog实例,而不注入gundog实例,显式的ref指定依赖覆盖自动装配指定的依赖。

注意:对于大型的应用,不建议使用自动苯配。虽然使用自动装配可减少配置文件的工作量,但大大降低了依赖关系的清晰性........件的属性名,导致bean与 bean之间的搞合降低到代码层次,不利于高层次解辑。