在 Spring 開發中,依賴注入 是核心機制。除了 Spring 專有的 @Autowired,Java EE 標準提供的 javax.annotation.Resource(JSR-250)同樣廣泛使用。本文深入解析 @Resource 的注入語義、屬性優先級、與 @Autowired 的本質區別,並給出生產級最佳實踐建議。
javax.annotation.Resource,屬於 Java EE / Jakarta EE 標準,不依賴 Spring,便於組件遷移。name(JNDI 名稱/Bean 名稱)、type(類型)、authenticationType、shareable、mappedName、description。當在字段或 Setter 上標註 @Resource 時,容器按以下順序查找目標 Bean:
name 屬性,直接按該名稱查找 Bean。name 時,默認使用字段名或 Setter 方法名(去掉 set 前綴、首字母小寫)作為 Bean 名稱 查找。type 屬性或字段/參數類型)查找,要求上下文中唯一匹配。// 1. 無屬性:按字段名 "personDao" 查找 Bean
@Resource
private PersonDao personDao;
// 2. 顯式指定 name:按 "specialDao" 查找
@Resource(name = "specialDao")
private PersonDao personDao;
// 3. 顯式指定 type + name:雙重保險
@Resource(name = "orderDao", type = OrderDao.class)
private OrderDao orderDao;
// 4. 作用於 Setter
@Resource(name = "userService")
public void setUserService(UserService userService) {
this.userService = userService;
}
| 維度 | @Resource (JSR-250) | @Autowired (Spring) |
|---|---|---|
| 標準歸屬 | Java EE / Jakarta EE 標準 | Spring 框架專有 |
| 默認匹配策略 | byName → byType | byType → byName (需配合 @Qualifier) |
| 指定名稱屬性 | name | 無,需配合 @Qualifier("beanName") |
| 指定類型屬性 | type | 自動推斷,無顯式屬性 |
| 必需性控制 | 無(配合 @Nullable 或 required=false 需 Spring 扩展) | required=false 允許為 null |
| 構造器注入 | JDK 9+ 支持 | 全版本支持,且單構造器可省略註解 |
| 多態注入靈活性 | 較弱,名稱優先 | 較強,類型優先 + Qualifier 精確控制 |
| 遷移友好度 | 高,無 Spring 依賴 | 低,耦合 Spring |
首選 @Resource。配合 name 明確指定 Bean 名稱,語義清晰:
@Resource(name = "redisTemplate")
private RedisTemplate<String, Object> redisTemplate;
@Autowired + @Qualifier 更直觀:
@Autowired
@Qualifier("mysqlDataSource")
private DataSource dataSource;
Spring 4.3+ 單構造器可省略 @Autowired,代碼最乾淨:
private final UserRepository userRepository;
private final OrderService orderService;
public OrderController(UserRepository userRepository, OrderService orderService) {
this.userRepository = userRepository;
this.orderService = orderService;
}
僅 @Autowired 支持:
@Autowired
private List<PaymentStrategy> strategies; // 注入所有 PaymentStrategy 實現
@Autowired
private Map<String, PaymentStrategy> strategyMap; // key 為 beanName
name,會報 NoSuchBeanDefinitionException。@Resource(字段注入)@Autowired 可省略@Autowired(required = false) 或 @Nullable @Resource(需 Spring 5+)。new Controller(mockRepo, mockSvc),零反射。Spring 通過 CommonAnnotationBeanPostProcessor 處理 @Resource,核心邏輯在 ResourceElement:
// 簡化邏輯
String name = resource.name();
if (!StringUtils.hasText(name)) {
name = member.getName(); // 字段名或 setter 方法名
}
if (beanFactory.containsBean(name)) {
return beanFactory.getBean(name, requiredType);
}
// 名稱找不到,嘗試按類型查找
return beanFactory.getBean(requiredType);
@Resource 作為 Java EE 標準,以 名稱優先、類型兜底 的語義提供了良好的可移植性;@Autowired 則是 Spring 生態的原生選擇,類型優先策略配合 @Qualifier 更適合複雜多態場景。現代 Spring 開發推薦:構造器注入為主,字段注入慎用;團隊統一一種風格,避免混用帶來的認知開銷。