前言:在Spring框架中,依赖注入(DI)是实现松耦合的核心机制之一。主要通过注解(如@Autowired
、@Resource
、@Inject
)来自动装配Bean。以下是它们的详细对比和使用场景分析:
一. 核心注解对比
注解 | 所属规范 | 默认行为 | 装配方式 | 适用场景 |
@Autowired | Spring | 按类型(byType ) | 优先按类型,可配合@Qualifier 按名称 | Spring项目首选,适合强类型依赖 |
@Resource | JSR-250 | 按名称(byName ) | 先按名称,失败后按类型 | 需要明确指定Bean名称时使用 |
@Inject | JSR-330 | 按类型(byType ) | 类似@Autowired ,但无required 属性 | 需要与Java标准兼容(如CDI环境) |
二. 常见问题
Q1: @Autowired
和@Resource
如何选择?
-
如果依赖的Bean名称明确且固定,用
@Resource(name="xxx")
更直观。 -
如果依赖的是接口或抽象类型,用
@Autowired
+@Qualifier
更灵活。
Q2: 为什么推荐用@Autowired
而非@Inject
?
-
@Autowired
是Spring原生注解,支持required
属性和更丰富的上下文匹配(如@Primary
、@Lazy
)。
Q3: 如何处理多个同类型Bean的冲突?
-
方案1:用
@Qualifier
/@Resource(name)
指定名称。 -
方案2:在其中一个Bean上标记
@Primary
,使其成为默认选择。
三. 特点对比
(1) @Autowired
特点:
-
Spring原生注解,默认按类型匹配Bean。
-
若存在多个同类型Bean,需配合
@Qualifier
指定名称。 -
支持
required=false
允许注入失败(默认true
)。
常见问题:
-
多个同类型Bean冲突:需用
@Qualifier
明确指定。 -
循环依赖:Spring通过三级缓存解决,但应避免设计上的循环依赖。
@Component
public class OrderService {
// 1. 直接按类型注入
@Autowired
private PaymentService paymentService;
// 2. 配合@Qualifier按名称注入
@Autowired
@Qualifier("alipayService")
private PaymentService paymentService;
// 3. 允许注入为null
@Autowired(required = false)
private DiscountService discountService;
}
(2) @Resource
特点:
-
Java标准注解(JSR-250),优先按名称(
name
属性)匹配,失败后按类型。 -
不支持
required
属性,若找不到Bean会直接抛异常。
适用场景:
-
需要显式指定Bean名称时(如多数据源配置)。
-
非Spring项目(如J2EE)中需要依赖注入。
@Component
public class OrderService {
// 1. 按名称注入(name属性)
@Resource(name = "wechatPayService")
private PaymentService paymentService;
// 2. 不指定name,先按字段名匹配,再按类型
@Resource
private PaymentService alipayService;
}
(3) @Inject
特点:
-
Java标准注解(JSR-330),功能与
@Autowired
类似,但无required
属性。 -
需搭配
javax.inject
包使用(需额外依赖)。
适用场景:
-
需要与Java生态兼容(如CDI、Quarkus等框架)。
-
避免Spring强耦合的场景。
import javax.inject.Inject;
import javax.inject.Named;
@Component
public class OrderService {
// 1. 按类型注入
@Inject
private PaymentService paymentService;
// 2. 按名称注入(需配合@Named)
@Inject
@Named("alipayService")
private PaymentService paymentService;
}
结尾:通过合理选择注解,可以更高效地管理依赖关系。在Spring生态中,@Autowired
是默认选择,而@Resource
和@Inject
在特定场景下补充使用。