Springboot依赖注入顺序问题
Springboot初始化的过程中,各个层已经相应的变量会进行依赖注入。但是,其中部分变量可能依赖于前面需要注入的变量,这就有一个先后问题。
一. 案例
下面是我用@Value进行依赖注入的时候,最初的一个状态。这是一个Service层的实现类,主要是做飞书应用相关配置。
1 |
|
飞书应用需要有appId和appSecret两个参数,用以构建飞书客户端应用。但是,测试环境和生产环境构成了两个不同的应用,所以分成两个配置文件来注入相应的变量。
但是,按照上述的方法,Client构建是无法成功的。
二. 原因
1. 依赖注入顺序问题(最主要的问题)
因为此时,appId和 appSecret还没有被 Spring 注入,它们的值是默认值(对于 String 来说就是 null)。
所以,实际上是用 null 值 去构建 Client,这会导致:
- 可能抛出
NullPointerException - 或者传入了无效的
appId和appSecret,导致后续调用飞书 API 失败
2. 根本原因:对象初始化顺序
首先我们要知道被 @Service 注解的类(以及其他 Spring 管理的组件,如 @Component、@Repository、@Controller 等)在 Spring 容器启动时就会被实例化一次,并且之后整个应用生命周期内都使用这同一个实例。
而Java 中对象的初始化顺序大致如下:
- 类加载,静态变量和静态块初始化
- 实例变量初始化(包括直接赋值与初始化块),此时依赖注入还未发生
- 构造函数执行
- 依赖注入(比如
@Value,@Autowired等) - 初始化回调(如
@PostConstruct方法)
所以,当执行到这一行:
1 | Client client = Client.newBuilder(appId, appSecret).build(); |
它是在 实例变量初始化阶段 执行的,而此时 appId和 appSecret还是 null,因为 Spring 还没给它们赋值。
三. 解决方案
为了解决这个问题,我们可以用上述第5个方法@PostConstruct来进行注解。
首先我们来了解一下@PostConstruct:在当前 Bean 的所有依赖注入完成之后,立即执行一次初始化方法。
使用场景
- 初始化资源(如连接池、缓存、定时任务)
- 校验注入的参数是否合法
- 执行一些只需执行一次的启动逻辑
特点:
| 特性 | 说明 |
|---|---|
| 执行时机 | 依赖注入完成后立即执行(在构造函数之后,afterPropertiesSet() 之前) |
| 执行次数 | 每个 Bean 实例只执行一次(即使它是 prototype) |
| 异常处理 | 如果方法抛出异常,Bean 创建失败,Spring 启动会中断 |
| 方法要求 | 必须是 无参方法,非静态,返回 void |
那么我们可以把上述Client的初始化修改为如下,就不会发生这样的问题了。
1 |
|
好了拜拜

- 标题: Springboot依赖注入顺序问题
- 作者: Sabthever
- 创建于 : 2025-10-27 16:55:12
- 更新于 : 2025-10-28 13:38:03
- 链接: https://sabthever.cn/2025/10/27/technology/java/依赖注入顺序问题/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。