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

相关推荐
leeyi6 分钟前
命令行里的平台:df_cli 都会什么(第108篇)
后端·aigc·agent
云雀衔光14 分钟前
Java Spring AI MCP:在 Spring 里把 AI 接上你的业务系统
java·开发语言·人工智能·后端·测试工具·spring
重生之小比特17 分钟前
【Java SE】数据类型与变量
java·开发语言·python
苏渡苇18 分钟前
Spring Insight 里如何对 Span 进行清洗
java·spring boot·后端·spring·系统监控
find1star18 分钟前
LeetCode 54:螺旋矩阵——用四个边界模拟矩阵收缩
java·算法·leetcode·边缘计算·学习方法
Yeniden21 分钟前
Java 后端从零到企业级:第1篇 Java 基础语法——变量、数据类型与运算符
java·开发语言·apache
邪修king22 分钟前
Linux系统篇(二十三) 基础 IO:从“文件”到“文件描述符”,彻底理解重定向
android·java·linux
云雀衔光31 分钟前
MCP + 应用生成:让 AI 直接产出可交互的应用
java·人工智能·测试工具·microsoft·交互·ai编程
Moment40 分钟前
为什么市面上的 coding agent 大多数都基于Nodejs?
前端·后端·面试
Nuanyt1 小时前
JVM常见核心知识梳理02 类加载 字节码技术 双亲委派 Java内存模型 JMM 并发底层 volatile synchronized 常见排障与调优工具
java·开发语言·jvm