自动连接协作者
Spring容器可以自动配置协作bean之间的关系。你可以通过检查ApplicationContext的内容,让Spring自动为你所需的bean解析协作bean(其他bean)。自动配置具有以下优点:
-
自动连线(Autowiring)可以显著减少指定属性或构造函数参数的需要。(其他机制,如bean模板(在本章的其他部分有讨论[参见../child-bean-definitions.md]),在这方面也同样有价值。)
-
随着对象的发展,自动连线可以更新配置。例如,如果你需要为一个类添加依赖项,这个依赖项可以自动得到满足,而无需你修改配置。因此,在开发过程中自动连线特别有用;当然,当代码库变得更加稳定时,也可以选择切换到显式连线方式。
在使用基于XML的配置元数据时(参见依赖注入),您可以使用<bean/>元素的autowire属性来指定bean定义的自动注入模式。自动注入功能有四种模式。您可以针对每个bean单独指定自动注入方式,从而选择要使用哪种自动注入模式。下表描述了这四种自动注入模式:
表1. 自动连线模式
| 模式 | 说明 |
|---|---|
no | (默认)不进行自动装配。Bean引用必须通过ref元素来定义。对于大型部署来说,不建议更改此默认设置,因为明确指定协作Bean可以提供更大的控制力和清晰性。在某种程度上,这也能反映系统的结构。 |
byName | 按属性名称进行自动装配。Spring会查找与需要自动装配的属性名称相同的Bean。例如,如果一个Bean定义设置为按名称自动装配,并且该Bean包含一个master属性(即它具有setMaster(..)方法),那么Spring会查找名为master的Bean定义,并使用该Bean来设置该属性。 |
byType | 如果容器中存在恰好一个该类型Bean,则允许该属性进行自动装配;如果存在多个同类型的Bean,则会抛出致命异常,表示不能对该Bean使用byType自动装配方式;如果没有匹配的Bean,则什么都不会发生(该属性不会被设置)。 |
constructor | 与byType类似,但适用于构造函数参数。如果容器中不存在恰好一个该类型构造函数参数的Bean,则会抛出致命错误。 |
使用byType或constructor自动装配模式,你可以装配数组和类型化集合。在这种情况下,容器中所有与预期类型匹配的自动装配候选对象都会被提供出来以满足依赖关系。如果预期的键类型是String,那么你可以自动装配强类型的Map实例。自动装配的Map实例的值由所有与预期类型匹配的bean实例组成,而Map实例的键则包含相应的bean名称。
自动装配的局限性和缺点
当自动配置在整个项目中被一致地使用时,其效果最佳。如果一般不使用自动配置,那么开发人员在仅为一两个bean定义使用自动配置时,可能会感到困惑。
考虑自动配线的局限性和缺点:
-
在
property和constructor-arg设置中明确的依赖关系总是会覆盖自动装配(autowiring)。你无法对简单的属性(如基本类型、String、Class以及这些简单属性的数组)进行自动装配。这种限制是故意设计的。 -
自动装配不如显式装配精确。不过,正如前面的表格中所提到的,Spring在遇到可能产生意外结果的歧义时,会小心避免猜测。由Spring管理的对象之间的关系不再有明确的文档说明。
-
编译器可能无法获取用于从Spring容器生成文档的接线(wiring)信息。
-
容器中可能存在多个与setter方法或构造函数参数指定的类型相匹配的bean定义以进行自动装配。对于数组、集合或
Map实例来说,这不一定是一个问题。然而,对于需要单个值的依赖关系,这种歧义并不会被随意解决。如果没有唯一的bean定义可用,就会抛出异常。
在后一种情况下,你有几个选择:
从自动配置中排除某个Bean
在每个 Bean 的基础上,你可以排除某个 Bean 参与自动注入。在 Spring 的 XML 格式中,将 <bean/> 元素的 autowire-candidate 属性设置为 false;而使用 @Bean 注解时,该属性的名称为 autowireCandidate。这样,容器就会让这个特定的 Bean 定义无法被自动注入机制识别,包括基于注解的注入点(如 @Autowired)。
autowire-candidate属性旨在仅影响基于类型的自动注入。它不会影响通过名称进行的显式引用,即使指定的bean没有被标记为自动注入候选者,这些引用仍然会被解析。因此,如果名称匹配,通过名称进行的自动注入仍会注入该bean。
你还可以根据bean名称的匹配模式来限制自动连接的候选者。顶层的<beans/>元素在其default-autowire-candidates属性中接受一个或多个模式。例如,要将自动连接的候选者限定为名称以Repository结尾的任何bean,可以提供*Repository作为值。要提供多个模式,请将它们定义在用逗号分隔的列表中。对于bean定义的autowire-candidate属性,显式的true或false值总是具有优先权。对于这样的bean,模式匹配规则将不适用。
这些技术对于那些你不希望通过自动配置(autowiring)被注入到其他bean中的bean来说非常有用。这并不意味着被排除在外的bean本身不能使用自动配置进行配置。相反,只是这种bean本身不适合作为自动配置其他bean的候选者。
从6.2版本开始,@Bean方法支持两种自动注入候选标志的变体:autowireCandidate和defaultCandidate。
当使用限定符时,带有defaultCandidate=false标记的bean仅能在存在额外限定符指示的注入点被使用。这对于那些只能在特定区域被注入、但不会妨碍其他地方相同类型bean使用的受限代理非常有用。这样的bean永远不会仅通过声明的类型被注入,而是需要类型加上特定的限定符才能被注入。
相比之下,autowireCandidate=false的行为与上面解释的autowire-candidate属性完全相同:这样的bean根本不会通过类型被注入。