Spring 构造器注入 vs 字段注入

一、核心结论(先背这个)

Spring 推荐构造器注入,而不推荐字段注入,
是因为构造器注入能保证对象在创建完成时依赖已经全部就绪,
而字段注入会让对象在一段时间内处于"不完整状态"。


二、两种注入方式的本质区别

1️⃣ 构造器注入(Constructor Injection)

java 复制代码
@Service
public class OrderService {

    private final OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}

本质:

  • 依赖作为构造器参数
  • 没有依赖就无法创建对象
  • 依赖在 new 之前就必须准备好

创建顺序(类比"深度优先"):

text 复制代码
创建 A
 → 先创建 B
   → 再创建 C
 → 再创建 A

2️⃣ 字段注入(Field Injection)

java 复制代码
@Service
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;
}

本质:

  • new 一个"空壳对象"
  • 再通过反射把依赖"塞进去"

创建顺序:

text 复制代码
new OrderService()   ← 依赖此时是 null
↓
反射注入 orderRepository

三、字段注入真实会出错的原因

❌ 出错根源(不是 Spring 的问题)

对象在依赖注入完成之前就已经存在,并且可能被使用


❌ 典型错误示例

java 复制代码
@Service
public class ReportService {

    @Autowired
    private UserRepository userRepository;

    public ReportService() {
        // 此时 userRepository 还没注入
        userRepository.findAll(); // 💥 NPE
    }
}

原因:

  • 构造器执行时,字段注入尚未发生
  • 依赖是 null

✅ 构造器注入不会有这个问题

java 复制代码
public ReportService(UserRepository userRepository) {
    this.userRepository = userRepository;
    userRepository.findAll(); // 一定安全
}

四、设计层面的差异(面试加分点)

字段注入的问题

  • 依赖关系 隐藏
  • 无法使用 final
  • 不利于单元测试
  • 容易掩盖设计问题(依赖过多)

构造器注入的优势

  • 依赖关系 一眼可见
  • 支持 final(不可变)
  • 创建即完整
  • 更容易测试
  • 循环依赖会更早暴露

五、你提出的"深度优先"理解(标准化表述)

构造器注入在 Bean 创建阶段会先解析并实例化其构造器参数,

形成一种类似 深度优先 的依赖构建过程,

从而保证对象在创建完成后依赖已经全部注入完成。

而字段注入是在对象实例化之后再进行依赖填充,

对象在此期间可能处于不完整状态。


六、30 秒面试速记版(终极版)

构造器注入是在对象创建时通过构造方法一次性注入依赖,

可以保证对象创建完成后就是可用状态;

字段注入是先创建对象再通过反射注入依赖,

对象可能短暂处于不完整状态,因此 Spring 官方更推荐构造器注入。

相关推荐
dovens6 分钟前
SpringBoot集成MQTT客户端
java·spring boot·后端
❀͜͡傀儡师11 分钟前
Spring Boot 集成 RocksDB 实战:打造高性能 KV 存储加速层
java·spring boot·后端·rocksdb
TeamDev19 分钟前
如何在 DotNetBrowser 中使用本地 AI 模型
前端·后端·.net
BENA ceic27 分钟前
Spring 的三种注入方式?
java·数据库·spring
小雅痞30 分钟前
[Java][Leetcode middle] 209. 长度最小的子数组
java·算法·leetcode
二哈赛车手41 分钟前
新人笔记---项目中简易版的RAG检索后评测指标(@Recall ,Mrr..)实现
java·开发语言·笔记·spring·ai
做时间的朋友。42 分钟前
精准核酸检测
java·数据结构·算法
Rust语言中文社区1 小时前
【Rust日报】2026-05-02 Temper - 用 Rust 编写的 Minecraft 服务器项目发布 0.1.0 版
运维·服务器·开发语言·后端·rust
许彰午1 小时前
CacheSQL(五):桥接篇
java·数据库·缓存·系统架构