Spring 依赖注入

一、三大基础注入方式

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 依赖注入。
相关推荐
2602_9599609212 分钟前
大厂Java面试:Spring Boot、JVM、Redis、Kafka与Elasticsearch在内容社区UGC场景下的实战拷问
java·jvm·spring boot·redis·面试题
再吃一根胡萝卜6 小时前
微服务治理的“四大护法”:从 Django 视角理解 Spring Cloud 核心组件
后端
再吃一根胡萝卜6 小时前
面试终极挑战:如何用 Django 经验,回答 Java 微服务实战问题?
后端
To_OC7 小时前
装完 ESLint 它一声不吭?我还以为代码写得多好
后端·node.js·eslint
St_rive7 小时前
Page Object设计模式
java·开发语言·设计模式
风流 少年8 小时前
Spring AI 2.0:SSE
java·人工智能·spring
凤山老林8 小时前
精细化流量治理:Spring Boot 动态特性开关与灰度发布体系
java·spring boot·后端
vipbic9 小时前
一个前端的 9 天重构:我是怎么用 Codex 重做航栈的
前端·javascript·后端
Aphelios38010 小时前
一次锁内网络IO引发的Tomcat线程池“饿死”事故
java·开发语言·spring boot·elasticsearch·tomcat·网络io阻塞·线程池耗尽
不可求~11 小时前
C++ std::string_view 不是字符串:从悬空引用到安全用法
java·开发语言·c++