Autowiring Collaborators
Spring 容器可以自动连接协作 Bean 之间的关系。你可以让 Spring 通过检查 ApplicationContext
的内容自动为你的 Bean 解析协作者(其他 Bean)。自动连接有以下优点:
-
自动装配可以显著减少指定属性或构造函数自变量的需求。(诸如 Bean 模板 discussed elsewhere in this chapter 之类的其它机制在这方面也非常有用。)
-
当你的对象演进时,自动装配可以更新配置。例如,如果你需要在某个类中添加依赖关系,该依赖关系可以自动满足,你不必修改配置。因此,自动装配在开发过程中尤其有用,而且并不会否定在代码库变得更稳定后切换到显式连接的选项。
当使用基于 XML 的配置元数据(请参阅 Dependency Injection)时,你可以使用 `<bean/>`元素的 `autowire`属性为 bean 定义指定自动连接模式。自动连接功能有四种模式。你可以针对每个 bean 指定自动连接,因此可以自行选择要自动连接哪些 bean。下表描述了四种自动连接模式:
Mode | Explanation |
---|---|
|
(默认)无自动装配。Bean 引用必须由 |
|
按属性名称自动装配。Spring 查找与需要自动装配的属性同名的 Bean。比如,如果 Bean 定义被设置为按名称自动装配,且其包含一个 |
|
允许只要容器中存在一个与属性类型完全匹配的 Bean,就自动装配该属性。如果存在多个 Bean,将引发致命异常,这表明您不能使用 |
|
与 |
通过 byType
或者 constructor
的自动装配模式,你可以连接数组和类型化集合。在这种情况下,容器内符合预期类型的所有自动装配候选都将提供,以便满足依赖关系。如果预期键类型是 String
,你可以自动装配强类型化的 Map
实例。自动装配的 Map
实例的值包含与预期类型相符的所有 Bean 实例,而 Map
实例的键则包含相应的 Bean 名称。
Limitations and Disadvantages of Autowiring
在整个项目中一致使用自动装配时,效果最佳。如果一般不使用自动装配,只有在连接一个或两个 Bean 定义时使用自动装配,这可能会让开发者感到困惑。
考虑自动装配的局限性和缺点:
-
property
和constructor-arg
设置中的显式依赖关系始终替代自动装配。你不能自动连接简单的属性,如基本类型、Strings
和Classes
(及其简单属性数组)。这种限制是设计本身固有的。 -
自动装配不如显式连接精确。虽然,正如之前表格中提到的,Spring 小心地避免猜测可能会产生意外结果的情况。你的 Spring 管理对象之间的关系不再显式记录。
-
连接信息可能对从 Spring 容器生成文档的工具不可用。
-
容器内的多个 Bean 定义可能与自动连接的 setter 函数或构造函数自变量指定的类型相匹配。对于数组、集合或
Map
实例而言,这并不是什么问题。然而,对于预期单个值的依赖关系,这种二义性并不能被随意解决。如果没有独特的 Bean 定义可用,将抛出异常。
在后一种情况下,你可以选择诸多选项:
-
放弃自动装配,使用显式连接。
-
通过将 Bean 定义的
autowire-candidate
属性设置成false
(如 next section 中描述),可以避免为 Bean 定义进行自动装配。 -
通过将
<bean/>
元素的primary
属性设成true
,可以将一个 Bean 定义设计为主要候选者。 -
实现基于标注的配置中可用的更细粒度的控制,如 Annotation-based Container Configuration 中描述。
Excluding a Bean from Autowiring
根据每个 bean,你可以将 bean 排除在自动连接之外。在 Spring 的 XML 格式中,将 <bean/>`元素的 `autowire-candidate`属性设置为 `false
。容器会使该特定的 bean 定义对自动连接基础设施不可用(包含注释样式的配置,例如 @Autowired
)。
|
你还可以根据 Bean 名称的模式匹配限制自动装配候选。顶级 <beans/>
元素在其 default-autowire-candidates
特性中接受一个或多个模式。例如,要将自动装配候选的状态限制为名称以 Repository
结尾的任何 Bean,请提供 *Repository
值。要提供多个模式,请在逗号分隔列表中定义它们。Bean 定义的 autowire-candidate
特性的明确 true
或 false
值始终优先。对于此类 Bean,模式匹配规则不适用。
这些技术对于你永远不想通过自动装配注入到其他 Bean 中的 Bean 非常有用。这并不意味着无法通过使用自动装配来自身配置被排除的 Bean。相反,Bean 本身不适合于自动装配其他 Bean。