聊聊@Autowired与@Resource的区别
1. 前言
从事过很多家公司,见过很多项目,发现@Autowired
和@Resource
的使用都是一样的乱,
一个项目中有使用@Autowired
的,有使用@Resource
的,
甚至有的类中一会儿使用@Autowired
,一会儿使用@Resource
,虽然不影响业务功能的实现,但看起来真的是杂乱无章。
本篇博客主要讲解这2个注解之间的区别。
2. 来源不同
@Autowired
是Spring框架的注解。
@Resource
是Java的注解(来自于JSR-250),由Spring框架兼容支持。
说明:JSR是Java Specification Requests的缩写,意思是Java规范提案。
3. 依赖查找顺序不同
@Autowired
先根据类型查找,如果存在多个Bean,再根据名称查找。
@Resource
先根据名称查找,如果查找不到,再根据类型查找。
3.1 验证@Autowired先根据类型查找,再根据名称查找
首先,新建接口:
public interface NotificationService {
void send();
}
然后新建第一个实现类:
import org.springframework.stereotype.Service;
@Service
public class EmailService implements NotificationService {
@Override
public void send() {
System.out.println("发送邮件通知");
}
}
接着新建第二个实现类:
import org.springframework.stereotype.Service;
@Service
public class SmsService implements NotificationService {
@Override
public void send() {
System.out.println("发送短信通知");
}
}
最后新建Controller,并使用@Autowired
来注入NotificationService:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RestController;
@RestController("/dependency/injection/test")
public class NotificationController {
@Autowired
private NotificationService notificationService;
}
此时启动项目,会抛出org.springframework.beans.factory.NoUniqueBeanDefinitionException
异常,
原因是因为有2个NotificationService类型的Bean,Spring不确定注入哪一个Bean,这也证明@Autowired
默认是先根据类型查找。
有三种解决方案可以解决该问题,
第一种解决方案是使用@Primary
注解:
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
@Service
@Primary
public class EmailService implements NotificationService {
@Override
public void send() {
System.out.println("发送邮件通知");
}
}
说明:如果有多个同类型的Bean,Spring会优先使用@Primary
注解标记的Bean。
第二种解决方案是修改字段名称:
@Autowired
private NotificationService emailService;
第三种解决方案是使用@Qualifier
注解:
@Autowired
@Qualifier("emailService")
private NotificationService notificationService;
第二种解决方案和第三种解决方案证明@Autowired
是根据名称查找的,
两者的区别是第二种解决方案是按字段名称查找的(隐式),第三种解决方案是按指定的名称查找的(显式)。
3.2 验证@Resource先根据名称查找,再根据类型查找
首先,新建接口:
public interface NotificationService {
void send();
}
然后新建第一个类(注意事项:不是实现类):
import org.springframework.stereotype.Service;
@Service
public class EmailService {
public void send() {
System.out.println("发送邮件通知");
}
}
接着新建第二个类(注意事项:是实现类):
import org.springframework.stereotype.Service;
@Service
public class SmsService implements NotificationService {
@Override
public void send() {
System.out.println("发送短信通知");
}
}
最后新建Controller,并使用@Resource
来注入NotificationService:
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController("/dependency/injection/test")
public class NotificationController {
@Resource
private NotificationService emailService;
}
此时启动项目,会抛出org.springframework.beans.factory.BeanNotOfRequiredTypeException
异常,
原因是因为按字段名称查找到的EmailService Bean,不是NotificationService类型,这也证明@Resource
默认是先根据名称查找。
有两种解决方案可以解决该问题,
第一种解决方案是显式指定Bean名称:
@Resource(name = "smsService")
private NotificationService emailService;
第二种解决方案是修改字段名称:
@Resource
private NotificationService notificationService;
第二种解决方案能注入成功,也证明@Resource
是根据类型查找的,
此时因为NotificationService只有一个实现类SmsService,所以直接注入成功,
如果将EmailService也改为NotificationService的实现类:
import org.springframework.stereotype.Service;
@Service
public class EmailService implements NotificationService {
@Override
public void send() {
System.out.println("发送邮件通知");
}
}
那么启动项目,会抛出org.springframework.beans.factory.NoUniqueBeanDefinitionException
异常。
4. 参数不同
@Autowired
只有1个required参数,@Resource
有name、type等7个参数。
4.1 @Autowired的参数
@Autowired
只有1个参数,如下所示:
public @interface Autowired {
boolean required() default true;
}
默认情况下,@Autowired
要求依赖必须存在,可以通过required = false
设置为可选。
@Autowired(required = false)
private NotificationService notificationService;
4.2 @Resource的参数
@Resource
有7个参数,如下所示:
public @interface Resource {
String name() default "";
String lookup() default "";
Class<?> type() default java.lang.Object.class;
enum AuthenticationType {
CONTAINER,
APPLICATION
}
AuthenticationType authenticationType() default AuthenticationType.CONTAINER;
boolean shareable() default true;
String mappedName() default "";
String description() default "";
}
默认情况下,@Resource
先根据字段名查找Bean,可以通过name参数显式指定名称,通过type参数显式指定类型。
@Resource(name = "emailService", type = NotificationService.class)
private NotificationService notificationService;
5. 支持的依赖注入方式不同
@Autowired
支持字段注入、Setter方法注入和构造函数注入。
@Resource
支持字段注入、Setter方法注入,不支持构造函数注入。
5.1 @Autowired支持的依赖注入方式
1)字段注入:
@RestController("/dependency/injection/test")
public class NotificationController {
@Autowired
private NotificationService notificationService;
}
这种方式不推荐使用,但在实际项目中使用的最多。
2)Setter方法注入:
@RestController("/dependency/injection/test")
public class NotificationController {
private NotificationService notificationService;
@Autowired
private void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}
}
3)构造函数注入
@RestController("/dependency/injection/test")
public class NotificationController {
private final NotificationService notificationService;
public NotificationController(NotificationService notificationService) {
this.notificationService = notificationService;
}
}
这种方式是Spring官方推荐的首选方式。
5.2 @Resource支持的依赖注入方式
1)字段注入:
@RestController("/dependency/injection/test")
public class NotificationController {
@Resource
private NotificationService notificationService;
}
2)Setter方法注入:
@RestController("/dependency/injection/test")
public class NotificationController {
private NotificationService notificationService;
@Resource
private void setNotificationService(NotificationService notificationService) {
this.notificationService = notificationService;
}
}
@Resource
不支持构造函数注入,如果在构造函数上使用@Resource
注解,IDEA会提示:
'@Resource' not applicable to constructor。
6. 总结
@Autowired
和@Resource
都是用来实现依赖注入的注解,但两者之间是有区别的,主要有以下4点:
来源不同
@Autowired
是Spring框架的注解。@Resource
是Java的注解(来自于JSR-250),由Spring框架兼容支持。依赖查找顺序不同
@Autowired
先根据类型查找,如果存在多个Bean,再根据名称查找。@Resource
先根据名称查找,如果查找不到,再根据类型查找。参数不同
@Autowired
只有1个required参数,@Resource
有name、type等7个参数。支持的依赖注入方式不同
@Autowired
支持字段注入、Setter方法注入和构造函数注入。@Resource
支持字段注入、Setter方法注入,不支持构造函数注入。
文章持续更新,欢迎关注微信公众号「申城异乡人」第一时间阅读!
聊聊@Autowired与@Resource的区别的更多相关文章
- java @Autowired与@Resource的区别
@Autowired与@Resource的区别 1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2.@Autowired默认 ...
- Spring 注释 @Autowired 和@Resource 的区别
Spring 注释 @Autowired 和@Resource 的区别 一. @Autowired和@Resource都可以用来装配bean,都可以写在字段上,或者方法上. 二. @Autowired ...
- @Autowired 与@Resource的区别(详细)
参考:@Autowired 与@Resource的区别(详细) spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource.@Pos ...
- java面试题之@Autowired和@Resource的区别
@Autowired和@Resource的区别: 1.都可以用来装配bean,都可以写在字段或者方法上: 2. @Autowired默认按类型装配,默认情况下必须要求依赖对象必须存在,如果允许为nul ...
- @Autowired 与@Resource的区别详解
spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource.@PostConstruct以及@PreDestroy. @Resour ...
- 关于@Autowired和@Resource注解区别
区分一下@Autowired和@Resource两个注解的区别: 1.@Autowired默认按照byType方式进行bean匹配,@Resource默认按照byName方式进行bean匹配 2.@A ...
- @Autowired 与@Resource的区别
1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2 @Autowired默认按类型装配(这个注解是属业spring的),默认情况下 ...
- @Autowired与@Resource的区别
1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2.@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必 ...
- spring @Autowired或@Resource 的区别
1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2.@Autowired默认按类型装配(这个注解是属于spring的),默认情况下必 ...
- Spring中@Autowired与@Resource的区别
1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2.@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必 ...
随机推荐
- Linux iostat 命令详解
Linux iostat 命令详解 在Linux系统管理中,监控磁盘I/O性能是一项至关重要的任务.iostat是sysstat包中的一个实用工具,用于监控和显示系统输入输出设备和CPU的使用情况.它 ...
- 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
在人工智能飞速发展的今天,大语言模型的应用越来越广泛.DeepSeek 作为近期爆火的一款大语言模型,受到了众多开发者的青睐. 今天这篇内容,就来聊聊,如何在本地自己的电脑上部署DeepSeek. 1 ...
- 用 C# 插值字符串处理器写一个 sscanf
插值字符串处理器 C# 有一个特性叫做插值字符串,使用插值字符串,你可以自然地往字符串里面插入变量的值,比如:$"abc{x}def",这一改以往通过 string.Format ...
- DevExpress WPF 在RibbonControl的Header中添加搜索框
主要代码: <dxb:BarEditItem Name="txtSearch" EditHorizontalAlignment="Center"> ...
- [WC2014] 紫荆花之恋 题解
啊啊啊啊啊啊啊啊啊啊啊我终于改完啦啊啊啊啊啊啊啊. 因为没有在最开始的时候将所有点设置为已经重构的,所以直接 \(R15-R70\) 间卡了两三天. 似乎也是我第一次大规模使用指针了. 这道题假如只有 ...
- C# List应用 Lambda 表达式
参考链接 : https://blog.csdn.net/wori/article/details/113144580 首先 => 翻译为{ } 然后没有然后 主要基于我工作中常用的几种情况,写 ...
- 2024.11.12随笔&联考总结
前言 心情不好,因为考试时 T2T3 全看错题了,导致 T2 没做出来,T3 一份没得.然后下午打球眼镜架子坏了,回机房才发现被高二的盒了. 但还是稍微写一下总结吧. 总结 感觉我今天做题状态还行,思 ...
- PVE 配置显卡直通
博客链接:PVE 配置显卡直通 配置 Device: Dell PowerEdge T630 CPU: Intel(R) Xeon(R) E5-2696 v4 x2 GPU 1: Matrox Ele ...
- 洛谷P10112 [GESP202312 八级] 奖品分配 题解
题目传送门. 看了题解才发现我有多蠢. 我的做法真是唐完了. 在此之前请学习扩展欧几里得定理和扩展欧几里得定理求逆元. 发现奖品要么 \(N\) 个,要么 \(N+1\) 个,于是分类讨论,当奖品只有 ...
- FastAPI 路径参数完全指南:从基础到高级校验实战 🚀
title: FastAPI 路径参数完全指南:从基础到高级校验实战 date: 2025/3/5 updated: 2025/3/5 author: cmdragon excerpt: 探讨 Fas ...