Java 中 Spring 怎么利用构造方法注入(Constructor Injection)实现强依赖的初始化

星宇同学_6691

星宇同学_6691

2026-07-25

251人浏览

原创

spring依赖注入主要有两种方式:构造方法注入和属性setter注入。构造方法注入通过构造函数参数强制传入依赖,确保对象创建即完整、不可变,适用于强依赖;setter注入则通过setter方法在对象创建后赋值,灵活性高但存在未初始化风险。

java 中 spring 怎么利用构造方法注入(constructor injection)实现强依赖的初始化

Spring 利用构造方法注入实现强依赖初始化,核心在于把依赖作为构造参数强制传入,确保对象一创建就具备完整、不可变的协作能力。这种方式天然契合“强依赖”语义——该依赖必须存在、不可为空、不该在后续被替换。

构造方法注入如何体现“强依赖”

强依赖指一个类正常运行所必需、且生命周期内不应变更的协作对象。构造方法注入通过以下机制体现这一点:

  • 编译期与运行期双重校验:构造函数参数类型明确,IDE 和编译器能提前发现缺失 Bean;Spring 启动时若找不到匹配 Bean,直接抛出 UnsatisfiedDependencyException,拒绝启动,不留下半成品对象。
  • 字段 final 修饰支持:依赖通常声明为 private final,构造中赋值后无法再修改,从语言层面锁定不变性,杜绝意外覆盖或空指针风险。
  • 无参构造器被禁用:只要定义了带参构造器,Java 默认无参构造器消失;Spring 无法绕过依赖直接 new 实例,强制依赖显式提供。

标准写法与关键细节

使用 @Autowired 注解在构造器上(Spring 4.3+ 单构造器可省略该注解),配合 final 字段是推荐实践:

OpenJDK 24
OpenJDK 24

OpenJDK 24 Windows x64 官方参考实现(24+36),适合 Windows 环境进行 Java 开发、编译、运行和版本兼容性验证。

下载
@Service
public class OrderService {
    private final PaymentService paymentService;
    private final InventoryService inventoryService;

    // Spring 4.3+ 中,单构造器可省略 @Autowired
    public OrderService(PaymentService paymentService, InventoryService inventoryService) {
        this.paymentService = paymentService;
        this.inventoryService = inventoryService;
    }

    public void placeOrder() {
        paymentService.charge();
        inventoryService.reserve();
    }
}
  • 多个依赖按需传入,顺序无关(Spring 按类型自动匹配,类型不唯一时用 @Qualifier 区分)。
  • 避免在构造器内调用 this 的其他方法(可能导致 this 提前暴露,破坏初始化完整性)。
  • 若依赖本身是 prototype 作用域,每次获取 OrderService 实例时,其构造器注入的 prototype Bean 也会重新创建(符合预期)。

对比 Setter 和字段注入,为什么更适合强依赖

Setter 注入允许对象先创建再设依赖,字段注入甚至允许 null 值暂存——二者都可能产生“部分初始化”的中间状态。而构造方法注入:

  • 不存在“已实例化但未注入”的窗口期,对象要么完整可用,要么根本造不出来。
  • 单元测试时可直接 new 并传入 mock 对象,无需启动容器,测试逻辑清晰可控。
  • 阅读代码时,仅看构造签名就能立刻掌握该类的最小运行契约,无需扫描全类查找 @Autowired 字段。

遇到循环依赖怎么办

构造器注入下,A 依赖 B、B 又依赖 A 会直接启动失败。这不是缺陷,而是设计警示:两个本该解耦的强依赖彼此缠绕,说明职责划分有问题。如确需保留,唯一安全解法是引入 @Lazy:

@Component
public class UserService {
    private final RoleService roleService;
    public UserService(@Lazy RoleService roleService) { // 延迟加载,打破构造时闭环
        this.roleService = roleService;
    }
}

注意:@Lazy 仅推迟依赖的实际解析时机,并不改变逻辑耦合;应优先重构拆分或引入中介层。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

2023.06.15

10737

6

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

2023.07.05

7862

9

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

2023.07.31

6832

8

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.01

1164

3

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.08.02

948

3

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

1396

5

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

2023.08.02

2829

5

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

2023.08.03

20131

3

配置java环境变量
配置java环境变量

配置Java环境变量是为了让操作系统能够识别和使用Java的相关命令和功能。本专题为大家提供配置java环境变量相关文章,帮助大家解决问题。

2023.08.03

1255

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习