# 2.2.4　通过为 bean 添加注解实现自动装配

简单来说，自动装配就是让 Spring 自动满足 bean 依赖的一种方法，在满足依赖的过程中，会在 Spring 应用上下文中寻找匹配某个 bean 需求的其他 bean。为了声明要进行自动装配，我们可以借助 Spring 的 @Autowired 注解。

比方说，考虑以下代码中的 CDPlayer 类：

{% code title="CDPlayer.java" %}

```java
package soundsystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class CDPlayer implements MediaPlayer {
  private CompactDisc cd;

  @Autowired
  public CDPlayer(CompactDisc cd) {
    this.cd = cd;
  }

  public void play() {
    cd.play();
  }

}
```

{% endcode %}

它的构造器上添加了 @Autowired 注解，这表明当 Spring 创建 CDPlayerbean 的时候，会通过这个构造器来进行实例化并且会传入一个可设置给 CompactDisc 类型的 bean，将一个 CompactDisc 注入到 CDPlayer 之中。

@Autowired 注解不仅能够用在构造器上，还能用在属性的 Setter 方法上。比如说，如果 CDPlayer 有一个 setCompactDisc() 方法，那 么可以采用如下的注解形式进行自动装配：

{% code title="CDPlayer.java" %}

```java
@Autowired
public void setCompactDisc(CompactDisc cd){
  this.cd = cd;
}
```

{% endcode %}

在 Spring 初始化 bean 之后，它会尽可能得去满足 bean 的依赖，在本例中，依赖是通过带有 @Autowired 注解的方法进行声明的，也就是 setCompactDisc()。

实际上，Setter 方法并没有什么特殊之处。@Autowired 注解可以用在类的任何方法上。假设 CDPlayer 类有一个 insertDisc() 方法， 那么 @Autowired 能够像在 setCompactDisc() 上那样，发挥完全相同的作用：

{% code title="CDPlayer.java" %}

```java
@Autowired
public void insertDisc(CompactDisc cd){
  this.cd = cd;
}
```

{% endcode %}

不管是构造器、Setter 方法还是其他的方法，Spring 都会尝试满足方法参数上所声明的依赖。假如有且只有一个 bean 匹配依赖需求的话，那 么这个 bean 将会被装配进来。如果没有匹配的 bean，那么在应用上下文创建的时候，Spring 会抛出 一个异常。为了避免异常的出现，你可以将 @Autowired 的 required 属性设置为 false：

{% code title="CDPlayer.java" %}

```java
@Autowired(required=false)
public CDPlayer(CompactDisc cd) {
  this.cd = cd;
}
```

{% endcode %}

将 required 属性设置为false 时，Spring 会尝试执行自动装配，但是如果没有匹配的 bean 的话，Spring 将会让这个 bean 处于未装配的状 态。但是，把 required 属性设置为 false 时，你需要谨慎对待。如果在你的代码中没有进行 null 检查的话，这个处于未装配状态的属性有可能会出现 NullPointerException。

如果有多个 bean 都能满足依赖关系的话，Spring 将会抛出一个异常，表明没有明确指定要选择哪个 bean 进行自动装配。在第 3 章中，我们会进一步讨论自动装配中的歧义性。

@Autowired 是 Spring 特有的注解。如果你不愿意在代码中到处使用 Spring 的特定注解来完成自动装配任务的话，那么你可以考虑将其替换为 @Inject：

```java
package soundsystem;
import javax.inject.Inject;
import javax.inject.Named;

@Named
public class CDPlayer {
  ...

  @Inject
  public CDPlayer(CompactDisc cd) {
    this.cd = cd;
  }
  
  ...
}
```

@Inject 注解来源于Java 依赖注入规范，该规范同时还为我们定义了 @Named 注解。在自动装配中，Spring 同时支持 @Inject 和 @Autowired。尽管 @Inject 和 @Autowired 之间有着一些细微的差别，但是在大多数场景下，它们都是可以互相替换的。

在 @Inject 和 @Autowired 中，我没有特别强烈的偏向性。实际上，在有的项目中，我会发现我同时使用了这两个注解。不过在本书的样例中，我会一直使用 @Autowired，而你可以根据自己的情况，选择其中的任意一个。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://potoyang.gitbook.io/spring-in-action-v4/di-2-zhang-zhuang-pei-bean/untitled/2.2.4-tong-guo-wei-bean-tian-jia-zhu-jie-shi-xian-zi-dong-zhuang-pei.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
