@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

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

相关推荐
身如柳絮随风扬7 分钟前
Java中的CAS机制详解
java·开发语言
韩立学长1 小时前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
风筝在晴天搁浅1 小时前
hot100 78.子集
java·算法
froginwe112 小时前
Scala 循环
开发语言
m0_706653232 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你912 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Bruk.Liu2 小时前
(LangChain实战2):LangChain消息(message)的使用
开发语言·langchain
qq_423233902 小时前
C++与Python混合编程实战
开发语言·c++·算法
m0_715575343 小时前
分布式任务调度系统
开发语言·c++·算法
Configure-Handler3 小时前
buildroot System configuration
java·服务器·数据库