题目
注入 Bean 的注解有哪些?@Autowired 和 @Resource 的区别是什么?
答案
@[toc]
---
## 注入 Bean 的注解有哪些?
Spring 内置的 `@Autowired` 以及 JDK 内置的 `@Resource` 和 `@Inject` 都可以用于注入 Bean。
| Annotaion | Package | Source |
| ------------ | ---------------------------------- | ------------ |
| `@Autowired` | `org.springframework.bean.factory` | Spring 2.5+ |
| `@Resource` | `javax.annotation` | Java JSR-250 |
| `@Inject` | `javax.inject` | Java JSR-330 |
`@Autowired` 和 `@Resource` 使用的比较多一些
## @Autowired 和 @Resource 的区别是什么?
`Autowired` 属于 Spring 内置的注解,**默认的注入方式为 `byType`(根据属性类型进行匹配)**,也就是说会优先根据接口类型去匹配并注入 Bean (接口的实现类)。
当一个接口存在多个实现类的话,`byType` 这种方式就无法正确注入对象了,因为这个时候 Spring 会同时找到多个满足条件的选择,默认情况下它自己不知道选择哪一个。**这种情况下,注入方式会变为 `byName`(根据属性名称进行匹配)**,这个名称通常就是类名(首字母小写)。就比如说下面代码中的 `smsService` 就是我这里所说的名称
```java
// smsService 就是我们上面所说的名称
@Autowired
private SmsService smsService;
```
> 举个例子,`SmsService` 接口有两个实现类: `SmsServiceImpl1`和 `SmsServiceImpl2`,且它们都已经被 Spring 容器所管理。
>
> ```java
> // 报错,byType 有多个且 byName 无法匹配
> @Autowired
> private SmsService smsService;
>
> // 正确注入 SmsServiceImpl1
> @Autowired
> private SmsService smsServiceImpl1;
>
> // 正确注入 SmsServiceImpl1
> // 通过 Qualifier 指定 name = "smsServiceImpl1"
> @Autowired
> @Qualifier(value = "smsServiceImpl1")
> private SmsService smsService;
> ```
>
> 我们还是建议通过 `@Qualifier` 注解来显示指定名称而不是依赖变量的名称。
`@Resource` 属于 JDK 提供的注解,和 @Autowired 恰恰相反,它的**默认注入方式为 `byName`。如果无法通过名称匹配到对应的 Bean 的话,注入方式会变为 `byType`**。
`@Resource` 有两个比较重要且日常开发常用的属性:`name`(名称)、`type`(类型)。
```java
public @interface Resource {
String name() default "";
Class<?> type() default Object.class;
}
```
如果仅指定 `name` 属性则注入方式为 `byName`,如果仅指定 `type` 属性则注入方式为 `byType`,如果同时指定`name` 和`type`属性(不建议这么做)则注入方式为 `byType` + `byName`。
> 举个例子,`SmsService` 接口有两个实现类: `SmsServiceImpl1`和 `SmsServiceImpl2`,且它们都已经被 Spring 容器所管理。
>
> ```java
> // 报错,byName 和 byType 都无法匹配到 bean
> @Resource
> private SmsService smsService;
>
> // 正确注入 SmsServiceImpl1
> @Resource
> private SmsService smsServiceImpl1;
>
> // 正确注入 SmsServiceImpl1 对象对应的 bean(比较推荐这种方式)
> @Resource(name = "smsServiceImpl1")
> private SmsService smsService;
> ```
简单总结一下:
- `@Autowired` 是 Spring 提供的注解,`@Resource` 是 JDK 提供的注解。
- `Autowired` 默认的注入方式为 `byType`(根据属性类型进行匹配),如果查不到则再根据属性名称进行匹配 `byName`
`@Resource` 默认注入方式为 `byName`,如果查不到则再根据属性类型进行匹配 `byType`
- 当一个接口存在多个实现类的情况下,`@Autowired` 和 `@Resource` 都需要通过名称才能正确匹配到对应的 Bean。`Autowired` 可以通过 `@Qualifier` 注解来显示指定名称,`@Resource` 可以直接通过内置的 `name` 属性来显示指定名称
