@Autowired 和 @Resource 的区别

@Autowired 和 @Resource 都是 Spring/Spring Boot 项目中,用来进行依赖注入的注解。它们都提供了将依赖对象注入到当前对象的功能,但二者却有众多不同, 其主要区别主要体现在以下 5 点:

  1. 来源不同;
  2. 依赖查找的顺序不同;
  3. 支持的参数不同;
  4. 依赖注入的支持不同;
  5. 编译器 IDEA 的提示不同。

1.来源不同

@Autowired 和 @Resource 来自不同的“父类”,其中 @Autowired 是 Spring 定义的注解,而 @Resource 是 Java 定义的注解,它来自于 JSR-250(Java 250 规范提案)。

小知识:JSR 是 Java Specification Requests 的缩写,意思是“Java 规范提案”。任何人都可以提交 JSR 给 Java 官方,但只有最终确定的 JSR,才会以 JSR-XXX 的格式发布,如 JSR-250,而被发布的 JSR 就可以看作是 Java 语言的规范或标准。

这里我们要注意, @Autowired跟Spring框架强耦合了, 如果换成其他框架,@Autowired就没作用了。而@Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持

 2.依赖查找顺序不同

依赖注入的功能,是通过先在 Spring IoC 容器中查找对象,再将对象注入引入到当前类中。而查找有分为两种实现:按名称(byName)查找或按类型(byType)查找,其中 @Autowired 和 @Resource 都是既使用了名称查找又使用了类型查找,但二者进行查找的顺序却截然相反。

2.1 @Autowired 查找顺序

@Autowired 是先根据类型(byType)查找,如果存在多个 Bean 再根据名称(byName)进行查找,这个名称通常就是类名(首字母小写)。就比如说下面代码中的 smsService 就是我这里所说的名称

举个例子,SmsService 接口有两个实现类: SmsServiceImpl1和 SmsServiceImpl2,且它们都已经被 Spring 容器所管理。

 这个时候我们还是建议通过 @Qualifier 注解来显示指定名称而不是依赖变量的名称。

@Autowired 的具体查找流程如下:

 关于以上流程,可以通过查看 Spring 源码中的 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues 实现分析得出,源码执行流程如下图所示:

 2.2 @Resource 查找顺序

@Resource 是先根据名称查找,如果(根据名称)查找不到,再根据类型进行查找,它的具体流程如下图所示:

 关于以上流程可以在 Spring 源码的 org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessPropertyValues 中分析得出。虽然 @Resource 是 JSR-250 定义的,但是由 Spring 提供了具体实现,它的源码实现如下:

 

 2.3 查找顺序小结

由上面的分析可以得出:

  • @Autowired 先根据类型(byType)查找,如果存在多个(Bean)再根据名称(byName)进行查找;
  • @Resource 先根据名称(byName)查找,如果(根据名称)查找不到,再根据类型(byType)进行查找。

 为了更好的理解,我们来看一下同一接口多个实现类,是如何注入的

接口:IAnimal

public Interface IAnimal{
    ......
}

实现类:DogImpl ,实现了IAnimal接口。

@Service("dogImpl")    //只写@Service 默认 value 为首字母小写 daoImpl 和 @Component 效果一样
public class DaoImpl impliments IAnimal{
    ...
}

业务类:AnimalController

public class AnimalController {
    @Autowired
    private IAnimal animal;
    ......
}

假如有一个“动物”的接口 IAnimalDogImpl类实现了接口 IAnimal, 且该接口只有 DogImpl这一个实现类,那么在引用实现类的时候,我们使用的是实现类的接口(像上面程序展示的那样)。Spring会按 byType的方式寻找接口的实现类,将其注入

假如有另一个实现类 CatImpl 也实现了接口 IAnimal, 这时候@Autowired去引用, 在同时存在两个实现类的情况下,会出现什么情况呢?

答:会报错。 这是由于 @Autowired 的特性决定的: @Autowired 的注入方式是 byType 注入, 当要注入的类型在容器中存在多个时,Spring是不知道要引入哪个实现类的,所以会报错。

@Service("catImpl")    
public class CatImpl impliments IAnimal{
    ...
}

 这张情况我们可以使用byName的方式

@Resource 默认是按照 byName 的方式注入的, 如果通过 byName 的方式匹配不到再按 byType 的方式去匹配。所以上面的引用可以替换为:

public class AnimalController {
    @Resource(name="dogImpl")        //实现类1中 @Service注解中标定的名称,不写默认是下面的名字
    private IAnimal dogImpl;
    
    @Resource(name="catImpl")        //实现类2中 @Service注解中标定的名称
    private IAnimal catImpl;
}

@Qualifier 注解也是 byName的方式,但是与@Resource 有区别,@Qualifier 使用的是 类名

public class AnimalController {
    @Qualifier("DaoImpl")        //实现类1的类名。注意区分与@Resource(name="dogImpl") 的区别。
    private IAnimal dogImpl;
    ......
}

 或者 @AutoWired + @Qualifier

public class AnimalController {
    @Autowired
	@Qualifier("dogImpl")
	private IAnimal animal;
    ......
}

3.支持的参数不同

@Autowired 和 @Resource 在使用时都可以设置参数,比如给 @Resource 注解设置 name 和 type 参数,实现代码如下:

 但二者支持的参数以及参数的个数完全不同,其中 @Autowired 只支持设置一个 required 的参数,表示是否开启自动注入默认是true。而 @Resource 支持 7 个参数,支持的参数如下图所示:

 

其中, @Resource 有两个比较重要且日常开发常用的属性:name(名称)、type(类型)。

如果仅指定 name 属性则注入方式为byName,如果仅指定type属性则注入方式为byType,如果同时指定name 和type属性(不建议这么做)则注入方式为byType+byName

4.依赖注入的支持不同

@Autowired 和 @Resource 支持依赖注入的用法不同,常见依赖注入有以下 3 种实现: 1. 属性注入 2. 构造方法注入 3. Setter 注入

这 3 种实现注入的实现代码如下。

4.1 属性注入

 4.2 构造方法注入

4.3 Setter 注入 

 其中,@Autowired 支持属性注入、构造方法注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入,当使用 @Resource 实现构造方法注入时就会提示以下错误:

 5.编译器提示不同

当使用 IDEA 专业版在编写依赖注入的代码时,如果注入的是 Mapper 对象,那么使用 @Autowired 编译器会提示报错信息,报错内容如下图所示:

 虽然 IDEA 会出现报错信息,但程序是可以正常执行的。 然后,我们再将依赖注入的注解更改为 @Resource 就不会出现报错信息了,具体实现如下:

 总结

@Autowired 和 @Resource 都是用来实现依赖注入的注解(在 Spring/Spring Boot 项目中),但二者却有着 5 点不同:

  1. 来源不同:@Autowired 来自 Spring 框架,而 @Resource 来自于(Java)JSR-250;
  2. 依赖查找的顺序不同:@Autowired 先根据类型再根据名称查询,而 @Resource 先根据名称再根据类型查询;
  3. 支持的参数不同:@Autowired 只支持设置 1 个参数,而 @Resource 支持设置 7 个参数;
  4. 依赖注入的用法支持不同:@Autowired 既支持构造方法注入,又支持属性注入和 Setter 注入,而 @Resource 只支持属性注入和 Setter 注入;
  5. 编译器 IDEA 的提示不同:当注入 Mapper 对象时,使用 @Autowired 注解编译器会提示错误,而使用 @Resource 注解则不会提示错误。

参考文档:https://www.cnblogs.com/jiaodaoniujava/p/17628232.html

                  @Autowired 和 @Resource_@resource @autowired-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值