当前位置: 首页 > news >正文

@Autowired和@Resource的区别

共同点

@Resource和@Autowired都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰效果相同,可以互相替换,不影响使用。

不同点

1、@Resource是JDK原生的注解,@Autowired是Spring2.5 引入的注解

2、@Resource有两个属性name和type。Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

@Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。

实践说明

定义接口做饭Cook.java,抽象方法open()cooking()close()

public interface Cook {
 
 /**
  * 开火
  */
 String open();
  /**
  * 炒菜
  */
  String cooking();
  /**
  * 关火
  */
  String close();
}

定义实现类炒西红柿CookTomato.java

/**
 * service接口 实现类
 * 炒西红柿
 */
@Service
public class CookTomato implements Cook {
  @override
 public String open() {
  return "炒西红柿前打开油烟机并开火";
 }
  @override
  public String cooking() {
  return "炒西红柿中~";
 }
  @override
  public String close() {
  return "炒西红柿后关闭油烟机并关火";
 }
}

定义Controller类CookController.java,注入Cook接口

/**
 * controller层
 */
@RestController
@RequestMapping("/cook")
public class CookController {
 
 @Resource
 private Cook cook;
 
 @RequestMapping("/open")
 public String open() {
  return cook.open();
 }
  
  @RequestMapping("/cooking")
 public String cooking() {
  return cook.cooking();
 }
  
  @RequestMapping("/close")
 public String close() {
  return cook.close();
 }
}

启动Spring Boot运行起来后请求三个接口都是正常的返回结果。

但是如果我们增加Cook接口的实现类

/**
 * service接口 实现类
 * 炒土豆
 */
@Service
public class CookPatato implements Cook {
  @override
 public String open() {
  return "炒土豆丝前打开油烟机并开火";
 }
  @override
  public String cooking() {
  return "炒土豆丝中~";
 }
  @override
  public String close() {
  return "炒土豆丝后关闭油烟机并关火";
 }
}

这个时候启动Spring Boot,控制台会报错

2021-10-24 10:24:10.662  WARN 5592 --- [  restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'CookController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.janeroad.annotation.service.Cook' available: expected single matching bean but found 2: CookTomato,CookPatato

大致意思是我们引入Cook但是Spring框架发现了有两个实现,无法匹配到bean

我们将代码改成这样

@Resource(name="cookTomato")
 private Cook cook;

或者

@Resource
@Qualifier("cookTomato")
 private Cook cook;

上述代码都在做一件事,把Cook实现类指定为炒西红柿实现类,启动Spring Boot后请求Controller接口就会发现一切正常!

如果我们不用@Resource注解改用@Autowire呢?

在上述改动基础上改成@Autowire会报以下错

Description:
 
Field cook in com.janeroad.annotation.controller.CookController required a single bean, but 2 were found:
 - cookTomato: defined in file [此处省略路径名]
 - cookPatato: defined in file [此处省略路径名]
 
 
Action:
 
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

报错意思就是CookController需要一个bean但是找到两种实现

所以我们就应该按照报错提示使用@Primary,在有多个实现bean时告诉Spring优先@Primary修饰的那个;或者使用@Qualifier来标注需要注入的类。

@Qualifier修改方式与@Resource的相同,一样是修改Controller代码中注入的Cook上面,这里不再复述

@Primary是修饰实现类的,告诉Spring,如果有多个实现类时,优先注入被@Primary注解修饰的那个。

那么修改CookTomato.java为

/**
 * service接口 实现类
 * 炒西红柿
 */
@Service
@Primary
public class CookTomato implements Cook {
  @override
 public String open() {
  return "炒西红柿前打开油烟机并开火";
 }
  @override
  public String cooking() {
  return "炒西红柿中~";
 }
  @override
  public String close() {
  return "炒西红柿后关闭油烟机并关火";
 }
}

启动Spring Boot后会发现,调用接口一切正常。

总结

@Autowired功能虽说非常强大,但是也有些不足之处。比如它跟Spring强耦合了,如果换成了其他框架,功能就会失效。而@Resource是JSR-250提供的,它是Java标准,绝大部分框架都支持。

除此之外,有些场景使用@Autowired无法满足的要求,改成@Resource却能解决问题。

1、@Autowired默认按byType自动装配,而@Resource默认byName自动装配。

2、@Autowired只包含一个参数:required,表示是否开启自动准入,默认是true。而@Resource包含七个参数,其中最重要的两个参数是:name 和 type。

3、@Autowired如果要使用byName,需要使用@Qualifier一起配合。而@Resource如果指定了name,则用byName自动装配,如果指定了type,则用byType自动装配。

4、@Autowired能够用在:构造器、方法、参数、成员变量和注解上,而@Resource能用在:类、成员变量和方法上。

5、@Autowired是Spring定义的注解,而@Resource是JSR-250定义的注解。

6、二者装配顺序不同

@Autowired

@Resource

相关文章:

  • kettle—数据库配置
  • WalletConnect的下一站——去中心化消息应用Web3inbox
  • SpringBoot的简介和使用
  • 9.SpringMVC环境搭建(XML启动方式)
  • Nginx 实战-负载均衡
  • 2022年河南省高等职业教育技能大赛软件测试赛项竞赛任务书
  • JDK8中Stream接口的常用方法
  • aws codedeploy 在ec2实例和autoscaling组上进行蓝绿部署
  • Python求矩阵的特征值和广义特征值
  • 【多线程】CAS
  • NDK(三):JNIEnv解析
  • 清理zabbix数据库ibdata1文件
  • 蛇形走线用在哪里,一文告诉你
  • 什么是“关键对话”?“关键对话”背后的底层思维是什么?如何进行一场“关键对话”?
  • java基础知识——11.方法
  • [LeetCode] Wiggle Sort
  • golang中接口赋值与方法集
  • Intervention/image 图片处理扩展包的安装和使用
  • JavaScript函数式编程(一)
  • log4j2输出到kafka
  • spring boot下thymeleaf全局静态变量配置
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 前端存储 - localStorage
  • 前端相关框架总和
  • 入口文件开始,分析Vue源码实现
  • 什么软件可以剪辑音乐?
  • 用Canvas画一棵二叉树
  • 鱼骨图 - 如何绘制?
  • 400多位云计算专家和开发者,加入了同一个组织 ...
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #162 (Div. 2)
  • $forceUpdate()函数
  • (2)STM32单片机上位机
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (学习日记)2024.01.19
  • (一)基于IDEA的JAVA基础12
  • (转)linux 命令大全
  • (转)winform之ListView
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .net FrameWork简介,数组,枚举
  • .Net语言中的StringBuilder:入门到精通
  • .pop ----remove 删除
  • /usr/local/nginx/logs/nginx.pid failed (2: No such file or directory)
  • ?php echo ?,?php echo Hello world!;?
  • @NestedConfigurationProperty 注解用法
  • @Resource和@Autowired的区别
  • [ C++ ] STL---stack与queue
  • [ vulhub漏洞复现篇 ] Hadoop-yarn-RPC 未授权访问漏洞复现
  • [ vulhub漏洞复现篇 ] struts2远程代码执行漏洞 S2-005 (CVE-2010-1870)
  • [2019.3.5]BZOJ1934 [Shoi2007]Vote 善意的投票
  • [ActionScript][AS3]小小笔记
  • [android] 练习PopupWindow实现对话框
  • [ASP.NET MVC]如何定制Numeric属性/字段验证消息