1.4.3 使用depends-on

如果一个bean是另一个bean的依赖项,在XML的配置中用元素来实现这一点。然而,有时bean之间的依赖关系并不直接。例如,当类中的静态初始值设定项需要触发时,例如数据库驱动程序注册。depends-on属性可以显式强制一个或多个bean在先初始化。以下示例使用depends-on属性表示对单个bean的依赖:

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />

要表示对多个bean的依赖关系,请提供一个bean名称列表作为depends-on属性的值(逗号、空白和分号是有效的分隔符):

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
    <property name="manager" ref="manager" />
</bean>

<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

depends-on属性既可以指定初始化时依赖项,也可以指定相应的销毁时依赖项(仅在单例bean的情况下)。定义被依赖项首先被销毁。因此,depends-on还可以控制停机顺序。

1.4.4. 惰加载bean

默认情况下,ApplicationContext一开始就创建和配置所有的单例bean,大部分情况下,这种预实例化是可取的,因为配置或周围环境中的错误会立即被发现。如果不需要马上加载,可以通过将bean定义标记为惰加载来防止单例bean的预实例化。一个惰加载bean告诉IOC容器在第一次请求bean实例时创建它,而不是在启动时。

在XML中,此行为由<bean/>元素上的lazy-init属性控制,如下示例所示:

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
<bean name="not.lazy" class="com.something.AnotherBean"/>

当applicationContext使用前面的配置时,当applicationContext启动时,lazy Bean不会被预先实例化,而not.lazy Bean则会被预先实例化。

但是,当一个惰加载bean是一个非惰加载的单例bean的依赖项时,ApplicationContext会在启动时创建惰加载bean,因为它必须满足单例的依赖项。惰加载bean被注入到其他惰加载的单例bean中。
您还可以通过在<beans/>元素上使用默认的 lazy-initialization属性在容器级别控制lazy初始化,下面的示例显示:

<beans default-lazy-init="true">
    <!-- no beans will be pre-instantiated... -->
</beans>

1.4.5 自动装配依赖项

Spring容器可以自动装配依赖bean之间的关系。通过检查ApplicationContext的内容,可以让Spring自动解析bean的依赖都(其他bean)。自动装配功能具有以下优点:

  • 自动装配可以显著减少指定属性或构造函数参数的需要。
  • 自动装配可以随着对象的发展更新配置。例如,如果需要向类添加依赖项,则可以自动满足该依赖项,而无需修改配置。因此,自动装配在开发期间尤其有用,而不需要在代码库变得更稳定时取消切换到显式布线的选项。

使用XML时,可以使用元素的autowire属性为bean定义指定自动装配模式。自动装配功能有四种模式。您可以为每个bean指定自动装配,从而可以选择要自动装配的对象。下表介绍了四种自动装配模式:
表2 自动装配模式

模式 说明
no (默认的模式)无自动装配。bean引用必须由ref元素定义。对于较大的部署,不建议更改默认设置,因为显式指定依赖项可以提供更大的控制和清晰性。在某种程度上,它记录了系统的结构。
byName 通过名字查找装配
byType 通过类型查找装配
constructor 类似于byType,但适用于构造函数参数。如果容器中不只有一个构造函数参数类型的bean,则会引发致命错误。

使用byType或构造函数自动装配模式,可以连接数组和集合。在这种情况下,将提供容器中与预期类型匹配的所有自动装配候选,以满足依赖关系。如果所需的键类型为字符串,则可以自动装配强类型映射实例。自动装配的映射实例的值由匹配预期类型的所有bean实例组成,并且映射实例的键包含相应的bean名称。

自动装配的局限性和缺点
在一个项目中全部使用自动装配时效果最好。如果一般不使用自动装配,开发人员可能会混淆使用它来连接一个或两个bean定义。

自动装配的局限性和缺点:

  • 属性和构造函数参数设置中的显式依赖项都是自动装配。不能自动装配简单属性,如基本类型、字符串和类(以及此类简单属性的数组)。这种限制是由设计造成的。
  • 自动装配不如显式装配精确。尽管如前表所述,Spring谨慎地避免猜测,以防出现可能产生意外结果的歧义。
  • 可能从Spring容器生成文档的工具可能无法获得依赖信息。
  • 容器中的多个bean定义可以与setter方法或要自动装配的构造函数参数指定的类型匹配。对于数组、集合或Map实例,这不一定是问题。但是,对于期望单个值的依赖项,这种模糊性不会被任意解决。如果没有唯一的bean定义可用,则引发异常。

在后一种方案中,您有几个选项:

  • 放弃自动装配,取而代之的是显式装配。
  • 通过将bean定义的autowire候选属性设置为false,避免自动连接bean定义,如下一节所述。
  • 通过将其<bean/>元素的主要属性设置为true,将单个bean定义指定为主要候选对象。
  • 实现基于注释的配置中可用的更细粒度的控件,如基于注释的容器配置中所述。

从自动装配中排除bean
在XML中,将··元素的autowire候选属性设置为false,可以排除自动装配。

autowire-candidate属性设计为只影响基于type的自动装配。它不会影响按名称显式引用,即使指定的bean没有标记为autowire候选对象,这些引用也会得到解析。因此,如果名称匹配,则按名称自动布线仍会注入bean。

您还可以根据模式匹配来限制自动装配候选对象。顶级的<beans/>元素在其=default-autowire-candidates属性中接受一个或多个模式。例如,要将autowire候选状态限制为名称以repository结尾的任何bean,请提供值*repository。要提供多个模式,请在逗号分隔的列表中定义它们。bean定义的autowire-candidate属性的显式值true或false始终优先。对于这种bean,模式匹配规则不适用。

这些技术对于您不希望通过自动装配注入其他bean的bean很有用。这并不意味着被排除的bean本身不能通过使用自动装配进行配置。相反,bean本身并不是自动装配其他bean的候选者。