Autowiring Collaborators

Spring 容器可以自动连接协作 Bean 之间的关系。你可以让 Spring 通过检查 ApplicationContext 的内容自动为你的 Bean 解析协作者(其他 Bean)。自动连接有以下优点:

  • 自动装配可以显著减少指定属性或构造函数自变量的需求。(诸如 Bean 模板 discussed elsewhere in this chapter 之类的其它机制在这方面也非常有用。)

  • 当你的对象演进时,自动装配可以更新配置。例如,如果你需要在某个类中添加依赖关系,该依赖关系可以自动满足,你不必修改配置。因此,自动装配在开发过程中尤其有用,而且并不会否定在代码库变得更稳定后切换到显式连接的选项。

当使用基于 XML 的配置元数据(请参阅 Dependency Injection)时,你可以使用 `<bean/>`元素的 `autowire`属性为 bean 定义指定自动连接模式。自动连接功能有四种模式。你可以针对每个 bean 指定自动连接,因此可以自行选择要自动连接哪些 bean。下表描述了四种自动连接模式:

Table 1. Autowiring modes
Mode Explanation

no

(默认)无自动装配。Bean 引用必须由 ref 元素定义。不建议更改默认设置大型部署,因为显式指定合作者可提供更高的控制度和清晰度。在某种程度上,它记录了系统的结构。

byName

按属性名称自动装配。Spring 查找与需要自动装配的属性同名的 Bean。比如,如果 Bean 定义被设置为按名称自动装配,且其包含一个 master 属性(即,它有一个 setMaster(..) 方法),Spring 会查找命名为 master 的 Bean 定义,并使用它来设置属性。

byType

允许只要容器中存在一个与属性类型完全匹配的 Bean,就自动装配该属性。如果存在多个 Bean,将引发致命异常,这表明您不能使用 byType 自动装配该 Bean。如果没有匹配的 Bean,则不作任何事情(属性未设置)。

constructor

byType 类似,但应用于构造函数参数。如果容器中不存在与构造函数参数类型完全匹配的 Bean,将引发致命错误。

通过 byType 或者 constructor 的自动装配模式,你可以连接数组和类型化集合。在这种情况下,容器内符合预期类型的所有自动装配候选都将提供,以便满足依赖关系。如果预期键类型是 String,你可以自动装配强类型化的 Map 实例。自动装配的 Map 实例的值包含与预期类型相符的所有 Bean 实例,而 Map 实例的键则包含相应的 Bean 名称。

Limitations and Disadvantages of Autowiring

在整个项目中一致使用自动装配时,效果最佳。如果一般不使用自动装配,只有在连接一个或两个 Bean 定义时使用自动装配,这可能会让开发者感到困惑。

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

  • propertyconstructor-arg 设置中的显式依赖关系始终替代自动装配。你不能自动连接简单的属性,如基本类型、StringsClasses(及其简单属性数组)。这种限制是设计本身固有的。

  • 自动装配不如显式连接精确。虽然,正如之前表格中提到的,Spring 小心地避免猜测可能会产生意外结果的情况。你的 Spring 管理对象之间的关系不再显式记录。

  • 连接信息可能对从 Spring 容器生成文档的工具不可用。

  • 容器内的多个 Bean 定义可能与自动连接的 setter 函数或构造函数自变量指定的类型相匹配。对于数组、集合或 Map 实例而言,这并不是什么问题。然而,对于预期单个值的依赖关系,这种二义性并不能被随意解决。如果没有独特的 Bean 定义可用,将抛出异常。

在后一种情况下,你可以选择诸多选项:

  • 放弃自动装配,使用显式连接。

  • 通过将 Bean 定义的 autowire-candidate 属性设置成 false(如 next section 中描述),可以避免为 Bean 定义进行自动装配。

  • 通过将 &lt;bean/&gt; 元素的 primary 属性设成 true,可以将一个 Bean 定义设计为主要候选者。

  • 实现基于标注的配置中可用的更细粒度的控制,如 Annotation-based Container Configuration 中描述。

Excluding a Bean from Autowiring

根据每个 bean,你可以将 bean 排除在自动连接之外。在 Spring 的 XML 格式中,将 <bean/>`元素的 `autowire-candidate`属性设置为 `false。容器会使该特定的 bean 定义对自动连接基础设施不可用(包含注释样式的配置,例如 @Autowired)。

autowire-candidate 属性设计为仅影响基于类型的自动装配。它不影响按名称明确引用,即使指定的 Bean 未标记为自动装配候选也能够得到解决。因此,按名称自动装配依然会注入 Bean,如果名称匹配。

你还可以根据 Bean 名称的模式匹配限制自动装配候选。顶级 <beans/> 元素在其 default-autowire-candidates 特性中接受一个或多个模式。例如,要将自动装配候选的状态限制为名称以 Repository 结尾的任何 Bean,请提供 *Repository 值。要提供多个模式,请在逗号分隔列表中定义它们。Bean 定义的 autowire-candidate 特性的明确 truefalse 值始终优先。对于此类 Bean,模式匹配规则不适用。

这些技术对于你永远不想通过自动装配注入到其他 Bean 中的 Bean 非常有用。这并不意味着无法通过使用自动装配来自身配置被排除的 Bean。相反,Bean 本身不适合于自动装配其他 Bean。