自动装配(autowiring)有助于减少甚至消除配置<property>
元素和<constructor-arg>
元素,让Spring自动识别如何装配Bean的依赖关系。
自动检测(autodiscovery)比自动装配更进了一步,让Spring能够自动识别哪些类需要被配置成Spring Bean,从而减少对<bean>
元素的使用。
1.自动装配Bean属性
(1)4种类型的自动装配
1)byName——把与Bean的属性具有相同名字(或者ID)的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的名字想匹配的Bean,则该属性不进行装配。
package com.springinaction.springidol;
public class Flute implements Instrument
{
public void play()
{
System.out.println("WOO WOO WOO");
}
}
通过设置autowire属性为byName,Spring将特殊对待penny的所有属性,为这些属性寻找与其名字相同的Spring Bean。在这里,Spring会发现instrument属性可以通过setter注入来进行自动装配。
<bean id="instrument" class="com.springinaction.springidol.Flute" />
<bean id="penny" class="com.springinaction.springidol.Instrumentalist"
autowire="byName">
<property name="song" value="Jingle Bells" />
</bean>
byName自动装配遵循一项约定:为属性自动装配ID与该属性的名字相同的Bean。
使用byName自动装配的缺点是需要假设Bean的名字与其他Bean的属性的名字一样。在我们的示例中,我们需要创建一个名为instrument的Bean。如果多个乐器演奏家(Instrumentalist)Bean都被配置为byName自动装配,那它们将会演奏同一乐器。
2)byType——把与Bean的属性具有相同类型的其他Bean自动装配到Bean的对应属性中。如果没有跟属性的类型相匹配的Bean,则该属性不被装配。
byType自动装配存在一个局限性:如果Spring寻找到多个Bean,它们的类型与需要自动装配的属性的类型都相匹配,Spring会抛出异常。
为了避免因为使用byType自动装配而带来的歧义,Spring为我们提供了另外两种选择:可以为自动装配标示一个首选Bean(primary=”true”,但是primary属性有个很怪异的一点:它默认设置为true。),或者可以取消某个Bean自动装配的候选资格(autowire-candidate=”false”)。
<bean id="instrument" class="com.springinaction.springidol.Flute"
primary="false" />
<bean id="instrument" class="com.springinaction.springidol.Flute"
autowire-candidate="false" />
注:Spring会优先选择与属性名字相同的Bean而不会抛出异常。
<bean id="instrument" class="com.springinaction.springidol.Flute" />
3)constructor——把与Bean的构造器入参具有相同类型的其他Bean自动装配到Bean构造器的对应入参中。
<bean id="poeticQueen" class="com.springinaction.springidol.PoeticJuggler"
autowire="constructor" />
constructor自动装配具有和byType自动装配相同的局限性。当发现多个Bean匹配某个构造器的入参时,Spring不会尝试猜测哪一个Bean更适合自动装配。此外,如果一个类有多个构造器,它们都满足自动装配的条件时,Spring也不会尝试猜测哪一个构造器更适合使用。
4)autodetect——首先尝试使用constructor进行自动装配。如果失败,再尝试使用byType进行自动装配。
2.默认自动装配
在根元素<beans>
上增加一个default-autowire属性
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"
default-init-method="turnOnLights" default-destroy-method="turnOffLights"
default-autowire="byType">
默认情况下,default-autowire属性被设置为none,标示所有Bean都不使用自动装配,除非Bean自己配置了autowire属性。
你可以在一个Spring应用上下文中定义多个配置文件,每一个配置文件都可以有自己的默认自动装配策略。
我们还可以使用<bean>
元素的autowire属性来覆盖<beans>
元素所配置的默认自动装配策略。
3.混合使用自动装配和显式装配
我们对某个Bean选择了自动装配策略,并不代表我们不能对该Bean的某些属性进行显式装配。我们仍然可以为任意一个属性配置<property>
元素,就像我们之前没有设置autowire一样。
<bean id="qenny" class="com.springinaction.springidol.Instrumentalist"
autowire="byType">
<property name="song" value="Jingle Bells" />
<property name="instrument" ref="saxophone" />
</bean>
当使用constructor自动装配策略时,我们必须让Spring自动装配构造器的所有入参——我们不能混合使用constructor自动装配策略和<constructor-arg>
元素。
<bean id="poeticEmperor" class="com.springinaction.springidol.PoeticJuggler"
autowire="constructor">
<constructor-arg value="15" />
</bean>