@Autowired和@Resource的区别

最近开发过程中经常看到项目中有的地方用@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()

~~~java public interface Cook {

/**
 * 开火
 */
String open();

/* * 炒菜 */ String cooking(); /* * 关火 */ String close(); } ~~~

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

~~~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接口

~~~java /** * 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接口的实现类

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

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

~~~bash 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

我们将代码改成这样

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

或者

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

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

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

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

~~~bash 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为

~~~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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值