这两个注解都是用来实现依赖注入的。
在 Spring 框架中,依赖注入(DI)是实现控制反转(IoC)的核心机制之一。通过 DI,对象无需自行创建或查找其依赖项,而是由外部容器负责注入。而目前实现依赖注入的两种主流方案便是使用 @Autowired
和 @Resource
注解。
依赖注入本质解决了什么问题?
依赖注入的本质是解决对象之间的直接依赖关系(耦合关系)问题,一个对象中需要使用其它对象时,通常会通过
new
关键字来显式创建出相关对象,这样的操作会导致各个对象之间高度耦合、对象难以复用等问题。而依赖注入是一种反向控制的思想,即对象不再直接操作其他对象,而是通过容器(例如 Spring)来进行依赖注入,容器在运行时动态地给对象注入其所需要的依赖关系,从而降低了对象之间的耦合度,并提高了对象的复用性。
理解了依赖注入,接下来进入正题,分析下 @Autowired
和 @Resource
注解注入机制的区别。
出身背景不同
-
@Autowired:Spring 原生注解,位于 org.springframework.beans.factory.annotation
包,其使用依赖于 Spring 框架。 -
@Resource:Java 标准注解(JSR-250 规范定义),位于 javax.annotation
包,可跨容器移植。
JSR 是 Java Specification Requests 的缩写,指的是由 JCP(Java Community Process)管理的一系列规范提议,旨在扩展和改进 Java 平台的功能。提议可由不同的组织或个人提出,这些提议提交通过后就会以 JSR-XXX 的方式发布,比如上述提到的 JSR-250 规范,就是定义了一系列通用注解
@PostConstruct
,@PreDestroy
, 和@Resource
等,用于简化应用程序的开发。
为什么使用
@Resource
注解可跨容器移植?因为@Resource
是 Java 官方标准注解,在任何支持 JSR-250 标准的地方都可以使用。比如我们现在的项目从 Spring 换到了其它的框架,使用@Resource
可保证正常的依赖注入,而使用@Autowired
的话,因为它是专属于 Spring 框架的,可能就会编译报错了。
注入策略不同
注入查找策略有两种:按名称(byName)查找或按类型(byType)查找。
-
@Autowired
注解默认是按照类型(byType)来查找装配依赖对象的,如果按照类型匹配到了多个 bean,则按照字段名称(byName)作为 bean 的名字去查找。如下:
// 优先按照 DatabaseService.class 类型查找,查找到多个就按照 'mysqlServiceImpl' 名称进行匹配
@Autowired
private DatabaseService mysqlServiceImpl;
如果查找到最终也找不到唯一匹配的 bean,则会抛出异常。为了避免异常情况,Spring 提供了以下措施:
-
设置 required=false:当设置 required=false
时,即使没有找到匹配的 bean,也不会抛出异常,而是将该依赖设为null
。
@Autowired(required = false)
private DatabaseService databaseService;
-
结合 @Qualifier 使用:当存在多个相同类型的 bean 时,可以通过 @Qualifier
注解指定具体的 bean 名称来进行精确注入。
@Autowired
@Qualifier("mysqlServiceImpl")
private DatabaseService databaseService;
-
@Resource
注解默认是按照名称(byName)来查找装配依赖对象的。@Resource
有两个重要的属性:name 和 type,而 Spring 将@Resource
注解的 name 属性解析为 bean 的名字,而 type 属性则解析为 bean 的类型。
-
按名称注入(默认):如果没有指定 name 属性,Spring 将尝试使用该成员变量的字段名作为 bean 的名字进行查找。例如,下边示例代码中字段名为 databaseService,Spring 会尝试查找名称为 databaseService 的 bean。如果按名称未能找到匹配的 bean,Spring 接下来会尝试基于类型(byType)来匹配。如果此时发现多个相同类型的 bean,则会抛出 NoUniqueBeanDefinitionException
异常,因为无法确定应选择哪个 bean 进行注入。
// 会优先尝试查找名为 'databaseService' 的 bean,找不到则按照 DatabaseService.class 类型再去查找
@Resource
private DatabaseService databaseService;
-
指定了 name 属性:Spring 会严格按照给定的名称查找对应的 bean 进行注入。
// 查找容器中名称为 'mysqlServiceImpl' 的 bean 进行注入
@Resource(name = "mysqlServiceImpl")
private DatabaseService databaseService;
-
指定了 type 属性:这种模式下,Spring 将忽略名称,而仅基于类型进行匹配。如果容器中存在多个相同类型的 bean,则会抛出异常。这时,我们要么确保只有一个符合条件的 bean,要么结合使用 name 属性来明确指定需要的 bean 名称。
// 按类型查找,需要确保能找到唯一的 bean,否则会抛出异常
@Resource(type = DatabaseService.class)
private DatabaseService databaseService;
注入支持不同
-
@Autowired
支持如下 3 种方式:
-
属性注入:直接在类的字段上使用 @Autowired
注解即可完成依赖注入。
public class BizService {
@Autowired
private DatabaseService databaseService;
}
-
构造方法注入:通过在构造函数上使用 @Autowired
注解来依赖注入,这也是 Spring 团队推荐的方式。
public class BizService {
private final DatabaseService databaseService;
@Autowired
public MyComponent(DatabaseService databaseService) {
this.databaseService = databaseService;
}
}
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies.
意思是:对于强制性依赖关系就用构造函数方式注入,对于可选依赖就用 setter 方式注入。
-
Setter 方法注入:通过在 setter 方法上使用 @Autowired
注解来依赖注入。
public class BizService {
private DatabaseService databaseService;
@Autowired
public void setDatabaseService(DatabaseService databaseService) {
this.databaseService = databaseService;
}
}
-
@Resource
注解只支持属性注入和 Setter 方法注入,使用@Resource
注解进行构造方法注入时 IDE 就会提示以下错误:

总结
-
出身背景不同: @Autowired
是 Spring 框架的,而@Resource
是 Java 的,是 JSR-250 规范中提供的; -
注入策略不同: @Autowired
注解先根据类型(byType)查找,如果存在多个 bean 再根据名称(byName)进行查找;而@Resource
注解是先根据名称(byName)查找,如果查找不到,再根据类型(byType)进行查找; -
注入支持不同: @Autowired
注解支持属性注入、构造方法注入和 Setter 注入,而@Resource
注解只支持属性注入和 Setter 注入。
您的鼓励对我持续创作非常关键,如果本文对您有帮助,请记得点赞、分享、在看哦~~~谢谢!
原文始发于微信公众号(Java驿站):阿里二面:谈谈 @Autowired 和 @Resource 两个注解的区别
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/312818.html