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之间的搞合降低到代码层次,不利于高层次解辑。