@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) |
| 多实现类注入 | 需要额外处理 | 名称匹配更高效 |
| 启动时处理开销 | 较高 | 较低 |
七、最佳实践建议
- 推荐使用场景:
- 纯Spring项目:优先使用
@Autowired+@Qualifier - 需要跨容器通用性:使用
@Resource - 构造器注入:用
@Autowired(Spring推荐方式)
- 避免的问题:
java
// 反例:字段注入+多个实现
@Autowired
private PaymentService paymentService;// 危险!
// 正例:明确指定
@Resource(name = "alipayPayment")
private PaymentService paymentService;
- 现代Spring开发建议:
java
@Service
public class OrderService {
private final PaymentService paymentService;
// 构造器注入(Spring 4.3+可省略@Autowired)
public OrderService(@Qualifier("creditCardPayment") PaymentService paymentService) {
this.paymentService = paymentService;
}
}
八、原理深度剖析
@Autowired 处理流程
- 扫描阶段:
BeanPostProcessor收集所有@Autowired注解 - 解析阶段:按类型从
BeanFactory查找匹配bean - 注入阶段:
- 字段注入:反射直接设值
- 方法注入:调用setter方法
- 异常处理:检查
required属性
@Resource 处理流程
- 名称解析:先检查
name属性或默认字段名 - 类型回退:名称找不到时按类型查找
- 注入执行:通过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 |
通过以上对比分析,开发者可以根据具体场景选择合适的依赖注入方式,构建更健壮的应用系统。