# 1.4.5. 自动装配协作者

Spring 容器可以自动装配协作 bean 之间的关系。您可以让 Spring 通过检查 `ApplicationContext` 的内容自动为您的 bean 解析协作者（其他 bean）。自动装配具有以下优点：

* 自动装配可以显着减少指定属性或构造函数参数的需要。[（本章其他地方讨论](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-child-bean-definitions)的 bean 模板等其他机制 在这方面也很有价值。）
* 随着对象的发展，自动装配可以更新配置。例如，如果您需要向类添加依赖项，则可以自动满足该依赖项，而无需修改配置。因此，自动装配在开发过程中特别有用，而不会在代码库变得更稳定时否定切换到显式装配的选项。

当使用基于 XML 的配置元数据时（请参阅[依赖注入](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-collaborators)），您可以使用`<bean/>`元素的`autowire`属性为 bean 定义指定自动装配模式。自动装配功能有四种模式。您指定每个 bean 的自动装配，因此可以选择要自动装配的那些。下表描述了四种自动装配模式：

| 模式            | 解释                                                                                                                                                       |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `no`          | （默认）不自动装配。Bean 引用必须由`ref`元素定义。对于较大的部署，不建议更改默认设置，因为明确指定协作者可以提供更大的控制力和清晰度。在某种程度上，它记录了系统的结构。                                                                |
| `byName`      | 按属性名称自动装配。Spring 寻找与需要自动装配的属性同名的 bean。例如，如果一个 bean 定义被设置为按名称自动装配并且它包含一个`master`属性（即它有一个 `setMaster(..)`方法），那么 Spring 会查找一个命名的 bean 定义`master`并使用它来设置该属性。 |
| `byType`      | 如果容器中恰好存在一个属性类型的 bean，则让属性自动装配。如果存在多个，则会抛出一个致命异常，这表明您可能不会`byType`对该 bean 使用自动装配。如果没有匹配的 bean，则不会发生任何事情（未设置属性）。                                           |
| `constructor` | 类似于`byType`但适用于构造函数参数。如果容器中没有一个构造函数参数类型的 bean，则会引发致命错误。                                                                                                  |

使用`byType`或`constructor`自动装配模式，您可以封装数组和类型化集合。在这种情况下，将提供容器中与预期类型匹配的所有自动装配候选者来满足依赖关系。如果预期的键类型是`String` ，您可以自动装配强类型`Map`实例。自动装配`Map` 实例的值包含与预期类型匹配的所有 bean 实例，并且 `Map`实例的键包含相应的 bean 名称。

**自动装配的限制和缺点**

自动装配在项目中一致使用时效果最佳。如果一般不使用自动装配，开发人员可能会混淆使用它来只装配一个或两个 bean 定义。

考虑自动装配的限制和缺点：

* `property`和`constructor-arg`设置中的显式依赖项总是覆盖自动装配。您不能自动装配简单属性，例如基元、 `Strings`和`Classes`（以及此类简单属性的数组）。此限制是设计使然。
* 自动装配不如显式装配精确。尽管如前表中所述，Spring 会小心避免猜测可能会产生意想不到的结果的歧义。Spring 管理的对象之间的关系不再明确记录。
* 从 Spring 容器生成文档的工具可能无法使用接线信息。
* 容器内的多个 bean 定义可能与要自动装配的 setter 方法或构造函数参数指定的类型匹配。对于数组、集合或 `Map`实例，这不一定是问题。但是，对于期望单个值的依赖项，这种歧义不会被任意解决。如果没有唯一的 bean 定义可用，则会引发异常。

在后一种情况下，您有多种选择：

* 放弃自动装配以支持显式装配。
* 通过将属性`autowire-candidate`设置为`false` 来避免对 bean 定义进行自动装配，如[下一节所述](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-autowire-candidate)。
* 通过将其`<bean/>`元素的`primary`属性设置为`true` ，将单个 bean 定义指定为主要候选者 。
* 使用基于注解的配置实现更细粒度的控制，如[基于注解的容器配置](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-annotation-config)中所述。

**从自动装配中排除 Bean**

在每个 bean 的基础上，您可以从自动装配中排除 bean。在 Spring 的 XML 格式中，将`<bean/>`元素的`autowire-candidate`属性设置为`false`. 容器使自动装配基础设施无法使用特定的 bean 定义（包括注解样式配置，例如[`@Autowired`](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-autowired-annotation)）。

`autowire-candidate`属性旨在仅影响基于类型的自动装配。它不会影响按名称的显式引用，即使指定的 bean 未标记为自动装配候选者，也会得到解析。因此，如果名称匹配，按名称自动装配仍然会注入一个 bean。

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

这些技术对于您永远不想通过自动装配注入其他 bean 的 bean 很有用。这并不意味着排除的 bean 本身不能通过使用自动装配来配置。相反，bean 本身不是自动装配其他 bean 的候选对象。
