一、三大基础注入方式
1. 构造器注入(官方推荐首选)
@Service
public class XxxService {
private final XxxDao xxxDao;
// 强制注入,依赖不可为空
public XxxService(XxxDao xxxDao) {
this.xxxDao = xxxDao;
}
}
- 优点:支持
final、强制依赖、减少空指针、缓解循环依赖 - 适用:项目核心必选依赖
2. Setter 设值注入
@Service
public class XxxService {
private XxxDao xxxDao;
@Autowired
public void setXxxDao(XxxDao xxxDao) {
this.xxxDao = xxxDao;
}
}
- 优点:灵活,容器初始化后可动态修改依赖
- 适用:非必需、可选依赖
3. 字段注入(不推荐生产使用)
@Service
public class XxxService {
@Autowired
private XxxDao xxxDao;
}
- 缺点:不能用 final、隐藏依赖、脱离 Spring 难以单元测试、更容易循环依赖
二、配套注入注解
1. @Autowired(Spring 原生,核心注入注解)
- 默认按类型匹配 Bean;
- 多个同类型 Bean 会报
NoUniqueBeanDefinitionException歧义异常; - 可作用于构造、set 方法、成员变量。
2. @Qualifier(@Autowired 配套限定注解,非独立注入方式)
作用:同接口多实现时,指定 Bean 名称精准匹配,解决注入冲突。 使用位置:构造参数、set 参数、成员变量上方
// 多实现场景
@Autowired
@Qualifier("mysqlUserDao")
private UserDao userDao;
3. @Primary(@Qualifier 替代方案)
在其中一个实现类添加,Spring 自动优先注入该 Bean,只能设置一个主 Bean,灵活性差。
@Repository
@Primary
public class MysqlUserDao implements UserDao {}
4. @Resource(JSR-250 规范)
-
优先按 Bean 名称匹配,无需搭配
@Qualifier; -
不支持构造方法注入。
@Resource(name = "mysqlUserDao")
private UserDao userDao;
5. @Inject(JSR-330 规范)
功能近似@Autowired,无required属性,需额外引入依赖,项目极少使用。
6. @Value(普通值注入)
注入字面量、配置文件属性(简单类型,非对象 Bean 注入)
@Value("${server.port}")
private Integer port;
三、集合批量注入
同类型所有 Bean 可直接注入到集合 / 数组,无需@Qualifier
@Autowired
private List<UserDao> daoList;
四、三种注入方式对比
| 注入方式 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|
| 构造器注入 | 依赖不可为空、线程安全、易测试、循环依赖少 | 可选依赖需重载构造 | ⭐⭐⭐⭐⭐ 生产首选 |
| Setter 注入 | 可动态修改依赖,适配可选依赖 | 实例创建后赋值,存在空指针风险 | ⭐⭐⭐ 仅可选依赖使用 |
| 字段注入 | 代码简洁、书写少 | 无法 final、难单元测试、隐藏依赖 | ⭐ 不推荐 |
五、总结
- 注入方式只有三类:构造注入、set 注入、字段注入;
@Autowired/@Resource/@Inject是实现注入的注解;@Qualifier/@Primary是辅助限定注解,用来解决多 Bean 冲突,不属于注入方式;@Value专门注入普通配置值,不用于对象 Bean 依赖注入。