⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 blog.csdn.net/mrxutada/article/details/118811930 「utada hikki」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

一、@Resource

@Resource是Java自己的注解

先来看一下源码:

@Resource有两个属性是比较重要的,分别是name和type;Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。默认按name进行注入。

下面看一下这样的一个变量注入方式:

按type进行注入的自动注入策略,这个type指的就是类的类型,可以这样理解,比如Apple.class,类型就是Apple,Person.class,类型就是Person。

如果我有两个Person类,这个时候就无法辨别注入对象,就可以使用name属性去辨别。

在spring中, 被@Component标识的类会在servlet容器启动时加载单实例(默认设置下),用@Resource注解可以注入,如果需要的bean没有被提前加载, 则会报错。

在加载的时,是根据类名(不包括package地址)判断,出现重复的类名会报异常(不在同一个package, 也会报异常)。如果类名相同,可以标识成不同的bean,然后@Resource的name去辨别。

假设,有两个相同的实现类,那么可以用name去辨别,如下:

@Service("a")
public class ReportServiceImpl implements ReportService{
......
}

@Service("b")
public class ReportServiceImpl implements ReportService{
......
}

注入的时候指定名称为a的那个实现类:

这样指定,就知道是哪一个了。

二、@AutoWired

@AutoWired是spring的注解,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier@Primary注解一起来修饰。@Resource默认按名称方式进行bean匹配,@Autowired默认按类型方式进行bean匹配。

使用@AutoWired变量注解方式时,会有黄色波浪线,idea会提示:

Spring团队建议:“在bean中始终使用基于构造函数的依赖注入。始终对强制依赖项使用断言”。

意思是说,用@AutoWired的注入时,尽量用基于构造函数的依赖注入,而不是变量的方式注入。

这就是构造函数方式的依赖注入:

再来看一下@AutoWired注解的源码:

只有required属性,没有其他属性了,根据type进行注入。

@AutoWired的变量注入时,如果碰到无法分辨的对象,就无法注入成功。但是可以结合@Qualifier注解使用,表明哪个实现类才是我们需要的。

但是仍然不建议使用变量注入方式

1、可能会造成NPE,如下:

public class TestController {
@Autowired
private TestService testService;
private String name;
public TestController(){
this.name= testService.getName();
}
}

这段代码执行时会报NPE。Java类会先执行构造函数,然后在通过@Autowired注入实例,二构造函数里面需要注入的对象,因此在执行构造函数的时候就会报错。

2、还可能回导致循环依赖,即A里面注入B,B里面又注入A。

注:在代码中发现构造方法中注入了很多依赖,显得很臃肿,对于这个问题,说明类中有太多的责任,违反了类的单一性职责原则,这时候需要考虑使用单一职责原则进行代码重构。

三、总结

简单来说,这两的区别就是:

  • **@Resource:**java的注解,属性较多,type无法分辨时可以用name分辨
  • **@Autowired:**spring的注解,一个属性,type无法分辨时需要借助@Qualifier注解才能使用,使用@Autowired方式最好使用构造函数的方式注入。

很简单的一个例子,有两个苹果,一个叫哈哈,一个叫呵呵,你指着两个苹果,意思是去拿个苹果,让@Resource去拿,如果不说明,他懵了,但是你说明拿叫哈哈的那个,他就知道了,给你拿来了,让@Autowired去拿,如果不说明,他也懵了,但是他又是个聋子,听不到你说的,结果就拿不到,但是如果写了个字条(@Qualifier)写明拿呵呵,他也就知道了。

文章目录
  1. 1. 一、@Resource
  2. 2. 二、@AutoWired
  3. 3. 三、总结