Autowiring Collaborators

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

The Spring container can autowire relationships between collaborating beans. You can let Spring resolve collaborators (other beans) automatically for your bean by inspecting the contents of the ApplicationContext. Autowiring has the following advantages:

  • Autowiring can significantly reduce the need to specify properties or constructor arguments. (Other mechanisms such as a bean template discussed elsewhere in this chapter are also valuable in this regard.)

  • Autowiring can update a configuration as your objects evolve. For example, if you need to add a dependency to a class, that dependency can be satisfied automatically without you needing to modify the configuration. Thus autowiring can be especially useful during development, without negating the option of switching to explicit wiring when the code base becomes more stable.

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

When using XML-based configuration metadata (see Dependency Injection), you can specify the autowire mode for a bean definition with the autowire attribute of the <bean/> element. The autowiring functionality has four modes. You specify autowiring per bean and can thus choose which ones to autowire. The following table describes the four autowiring modes:

Table 1. Autowiring modes
Mode Explanation

no

(Default) No autowiring. Bean references must be defined by ref elements. Changing the default setting is not recommended for larger deployments, because specifying collaborators explicitly gives greater control and clarity. To some extent, it documents the structure of a system.

byName

Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master and uses it to set the property.

byType

Lets a property be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown, which indicates that you may not use byType autowiring for that bean. If there are no matching beans, nothing happens (the property is not set).

constructor

Analogous to byType but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised.

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

With byType or constructor autowiring mode, you can wire arrays and typed collections. In such cases, all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Map instances if the expected key type is String. An autowired Map instance’s values consist of all bean instances that match the expected type, and the Map instance’s keys contain the corresponding bean names.

Limitations and Disadvantages of Autowiring

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

Autowiring works best when it is used consistently across a project. If autowiring is not used in general, it might be confusing to developers to use it to wire only one or two bean definitions.

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

Consider the limitations and disadvantages of autowiring:

  • Explicit dependencies in property and constructor-arg settings always override autowiring. You cannot autowire simple properties such as primitives, Strings, and Classes (and arrays of such simple properties). This limitation is by-design.

  • Autowiring is less exact than explicit wiring. Although, as noted in the earlier table, Spring is careful to avoid guessing in case of ambiguity that might have unexpected results. The relationships between your Spring-managed objects are no longer documented explicitly.

  • Wiring information may not be available to tools that may generate documentation from a Spring container.

  • Multiple bean definitions within the container may match the type specified by the setter method or constructor argument to be autowired. For arrays, collections, or Map instances, this is not necessarily a problem. However, for dependencies that expect a single value, this ambiguity is not arbitrarily resolved. If no unique bean definition is available, an exception is thrown.

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

In the latter scenario, you have several options:

  • Abandon autowiring in favor of explicit wiring.

  • Avoid autowiring for a bean definition by setting its autowire-candidate attributes to false, as described in the next section.

  • Designate a single bean definition as the primary candidate by setting the primary attribute of its <bean/> element to true.

  • Implement the more fine-grained control available with annotation-based configuration, as described in Annotation-based Container Configuration.

Excluding a Bean from Autowiring

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

On a per-bean basis, you can exclude a bean from autowiring. In Spring’s XML format, set the autowire-candidate attribute of the <bean/> element to false. The container makes that specific bean definition unavailable to the autowiring infrastructure (including annotation style configurations such as @Autowired ).

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

The autowire-candidate attribute is designed to only affect type-based autowiring. It does not affect explicit references by name, which get resolved even if the specified bean is not marked as an autowire candidate. As a consequence, autowiring by name nevertheless injects a bean if the name matches.

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

You can also limit autowire candidates based on pattern-matching against bean names. The top-level <beans/> element accepts one or more patterns within its default-autowire-candidates attribute. For example, to limit autowire candidate status to any bean whose name ends with Repository, provide a value of *Repository. To provide multiple patterns, define them in a comma-separated list. An explicit value of true or false for a bean definition’s autowire-candidate attribute always takes precedence. For such beans, the pattern matching rules do not apply.

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

These techniques are useful for beans that you never want to be injected into other beans by autowiring. It does not mean that an excluded bean cannot itself be configured by using autowiring. Rather, the bean itself is not a candidate for autowiring other beans.