> For the complete documentation index, see [llms.txt](https://potoyang.gitbook.io/spring-in-action-v4/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](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).

# 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，而你可以根据自己的情况，选择其中的任意一个。
