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 官方更推荐构造器注入。

相关推荐
To_OC3 小时前
从一行入口代码啃透 NestJS:工厂模式、装饰器和依赖注入是怎么串起来的
后端·设计模式·nestjs
Python私教3 小时前
多个项目怎么安全合并?先适配,再切换
后端·python·架构
2601_963870204 小时前
【计算机毕业设计】基于Spring Boot的专科医院医疗管理系统
java·spring boot·课程设计
Bingo_BIG4 小时前
Java Spring 批量修改,实体、接口、方法的定义
java·spring
画中有画4 小时前
软件架构中质量属性(性能、安全、可扩展性)的权衡设计
java·运维·安全
Shaoxi Zhang4 小时前
JAVA学习笔记035——对象和JSON格式
java·笔记·学习
赵丙双4 小时前
CountDownLatch 源码分析
java·aqs·countdownlatch
Python私教5 小时前
从表格到管理系统:别先写页面,先补齐权限、流程和审计
数据库·后端·架构
余额瞒着我当琳5 小时前
C++--深拷贝三件套 + swap + 写时拷贝 + vector 扩容 + reserve
java·开发语言·c++
thefool1122665 小时前
翻转二叉树
java