@Autowired 与 @Resource区别解析

@Autowired 与 @Resource 注解深度解析

一、核心区别对比

特性 @Autowired @Resource
来源 Spring 框架原生注解 JSR-250 标准注解
默认注入方式 按类型(byType) 按名称(byName)
required属性 支持(默认true) 不支持
名称指定方式 需配合@Qualifier 自带name属性
适用场景 Spring生态项目 需要跨框架通用性

二、源码级机制解析

1. @Autowired 工作原理

Spring通过AutowiredAnnotationBeanPostProcessor实现处理:

java 复制代码
public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
// 处理@Autowired字段注入
private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) {
// 反射查找@Autowired注解字段和方法
}

// 实际注入逻辑
protected void inject(Object bean, String beanName, PropertyValues pvs) {
// 通过BeanFactory按类型解析依赖
}
}

2. @Resource 工作原理

由CommonAnnotationBeanPostProcessor处理:

java 复制代码
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessor {
// 处理@Resource注入
protected Object getResourceToInject(Object target, String requestingBeanName) {
// 先按name查找,找不到再按type查找
}
}

三、实战案例对比

案例1:基础注入场景

java 复制代码
// 服务接口
public interface PaymentService {
void process();
}

// 实现类1
@Service("creditCardPayment")
public class CreditCardPayment implements PaymentService {
public void process() {
System.out.println("信用卡支付");
}
}

// 实现类2
@Service("alipayPayment")
public class AlipayPayment implements PaymentService {
public void process() {
System.out.println("支付宝支付");
}
}
使用@Autowired
java 复制代码
@Controller
public class OrderController {

// 方式1:可能报错(存在多个实现)
@Autowired// 抛出NoUniqueBeanDefinitionException
private PaymentService paymentService;

// 方式2:配合@Qualifier
@Autowired
@Qualifier("alipayPayment")
private PaymentService qualifiedService;

// 方式3:构造函数注入
@Autowired
public OrderController(@Qualifier("creditCardPayment") PaymentService service) {
this.paymentService = service;
}
}
使用@Resource
java 复制代码
@Controller
public class OrderController {

// 方式1:默认按名称匹配
@Resource(name = "alipayPayment")
private PaymentService paymentService;

// 方式2:不指定name时先按字段名匹配,再按类型
@Resource// 自动匹配名为creditCardPayment的bean
private PaymentService creditCardPayment;
}

案例2:集合类型注入

java 复制代码
// 多个同类型Bean
@Service
public class WechatPayment implements PaymentService {
public void process() {
System.out.println("微信支付");
}
}
@Autowired 处理集合
java 复制代码
@RestController
public class PaymentController {

// 自动注入所有PaymentService实现
@Autowired
private List<PaymentService> allPaymentServices;// 包含3个实现

@GetMapping("/payments")
public void listPayments() {
allPaymentServices.forEach(PaymentService::process);
}
}
@Resource 无法直接支持集合注入

四、混合使用场景

案例3:第三方库组件集成

java 复制代码
// 来自其他jar包的组件
public class ExternalService {
private DataSource dataSource;

@Resource// 标准注解,不依赖Spring
public void setDataSource(DataSource ds) {
this.dataSource = ds;
}
}

// Spring配置类
@Configuration
public class AppConfig {

@Bean
public ExternalService externalService() {
return new ExternalService();
}

@Bean
@Qualifier("mainDS")
public DataSource mainDataSource() {
return new HikariDataSource();
}
}

五、异常情况处理

@Autowired 典型异常

java 复制代码
@Component
public class InvalidExample {

// 抛出NoSuchBeanDefinitionException
@Autowired(required = true)// 默认值
private NonExistentService service;

// 抛出NoUniqueBeanDefinitionException
@Autowired
private PaymentService paymentService;// 有多个实现
}

@Resource 典型异常

java 复制代码
@Component
public class ResourceExample {

// 抛出NoSuchBeanDefinitionException
@Resource(name = "unknownBean")
private Object unknown;

// 按名称找不到时尝试按类型,若类型不唯一会报错
@Resource
private PaymentService service;// 可能抛出NoUniqueBeanDefinitionException
}

六、性能对比

操作 @Autowired @Resource
单类型注入 快(直接类型匹配) 中等(先name后type)
多实现类注入 需要额外处理 名称匹配更高效
启动时处理开销 较高 较低

七、最佳实践建议

  1. 推荐使用场景
  • 纯Spring项目:优先使用@Autowired + @Qualifier
  • 需要跨容器通用性:使用@Resource
  • 构造器注入:用@Autowired(Spring推荐方式)
  1. 避免的问题
java 复制代码
// 反例:字段注入+多个实现
@Autowired
private PaymentService paymentService;// 危险!

// 正例:明确指定
@Resource(name = "alipayPayment")
private PaymentService paymentService;
  1. 现代Spring开发建议
java 复制代码
@Service
public class OrderService {

private final PaymentService paymentService;

// 构造器注入(Spring 4.3+可省略@Autowired)
public OrderService(@Qualifier("creditCardPayment") PaymentService paymentService) {
this.paymentService = paymentService;
}
}

八、原理深度剖析

@Autowired 处理流程

  1. 扫描阶段:BeanPostProcessor收集所有@Autowired注解
  2. 解析阶段:按类型从BeanFactory查找匹配bean
  3. 注入阶段:
  • 字段注入:反射直接设值
  • 方法注入:调用setter方法
  1. 异常处理:检查required属性

@Resource 处理流程

  1. 名称解析:先检查name属性或默认字段名
  2. 类型回退:名称找不到时按类型查找
  3. 注入执行:通过Common Annotations API实现

九、扩展应用场景

自定义限定器

java 复制代码
// 自定义限定注解
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface AlipayQualifier {}

// 使用方式
@Controller
public class CustomController {

@Autowired
@AlipayQualifier
private PaymentService paymentService;
}

// 实现类标记
@Service
@AlipayQualifier
public class AlipayPayment implements PaymentService {
// 实现代码
}

十、版本兼容性

Spring版本 @Autowired 特性 @Resource 支持
2.5+ 基本功能支持 需要手动启用注解驱动
3.0+ 支持构造器注入 自动检测JSR-250注解
4.3+ 构造器注入可省略@Autowired 完整支持
5.0+ 支持Nullable注解 兼容Jakarta EE 9

通过以上对比分析,开发者可以根据具体场景选择合适的依赖注入方式,构建更健壮的应用系统。

相关推荐
你的冰西瓜2 小时前
C++中的vector容器详解
开发语言·c++·stl
刻BITTER2 小时前
C++ 获取任意整数类型的最大、最小值和长度
开发语言·c++
Gu_yyqx2 小时前
Maven管理工具
java·maven
悦悦子a啊2 小时前
Maven 项目实战入门之--学生管理系统
java·数据库·oracle
晨光32112 小时前
Day34 模块与包的导入
java·前端·python
知行合一。。。2 小时前
Python--01--核心基础
android·java·python
宵时待雨2 小时前
C语言笔记归纳22:预处理详解
c语言·开发语言·笔记
计算机毕设指导62 小时前
基于微信小程序的水上警务通系统【源码文末联系】
java·spring boot·mysql·微信小程序·小程序·tomcat·maven
陌生的人儿2 小时前
老年痴呆患者心血管防护,硝酸甘油使用需 “专人监护”
java·eclipse·tomcat·maven·0.3mg硝酸甘油舌下片