Springboot依赖注入顺序问题

Sabthever

  Springboot初始化的过程中,各个层已经相应的变量会进行依赖注入。但是,其中部分变量可能依赖于前面需要注入的变量,这就有一个先后问题

一. 案例

  下面是我用@Value进行依赖注入的时候,最初的一个状态。这是一个Service层的实现类,主要是做飞书应用相关配置。

1
2
3
4
5
6
7
8
9
@Service
public class FeishuServiceImpl implements FeishuService {
@Value("${feishu.appId}")
private String appId;
@Value("${feishu.appSecret}")
private String appSecret;
// 构建client
private Client client = Client.newBuilder(appId, appSecret).build();
}

  飞书应用需要有appIdappSecret两个参数,用以构建飞书客户端应用。但是,测试环境和生产环境构成了两个不同的应用,所以分成两个配置文件来注入相应的变量。

  但是,按照上述的方法,Client构建是无法成功的。

二. 原因

1. 依赖注入顺序问题(最主要的问题)

  因为此时,appIdappSecret还没有被 Spring 注入,它们的值是默认值(对于 String 来说就是 null)。

所以,实际上是用 null 值 去构建 Client,这会导致:

  • 可能抛出 NullPointerException
  • 或者传入了无效的 appIdappSecret,导致后续调用飞书 API 失败

2. 根本原因:对象初始化顺序

  首先我们要知道被 @Service 注解的类(以及其他 Spring 管理的组件,如 @Component@Repository@Controller 等)在 Spring 容器启动时就会被实例化一次,并且之后整个应用生命周期内都使用这同一个实例

  而Java 中对象的初始化顺序大致如下:

  1. 类加载,静态变量和静态块初始化
  2. 实例变量初始化(包括直接赋值与初始化块),此时依赖注入还未发生
  3. 构造函数执行
  4. 依赖注入(比如 @Value, @Autowired等)
  5. 初始化回调(如 @PostConstruct方法)

  所以,当执行到这一行:

1
Client client = Client.newBuilder(appId, appSecret).build();

  它是在 实例变量初始化阶段 执行的,而此时 appIdappSecret还是 null,因为 Spring 还没给它们赋值。

三. 解决方案

  为了解决这个问题,我们可以用上述第5个方法@PostConstruct来进行注解。

  首先我们来了解一下@PostConstruct在当前 Bean 的所有依赖注入完成之后,立即执行一次初始化方法。

  • 使用场景

    • 初始化资源(如连接池、缓存、定时任务)
    • 校验注入的参数是否合法
    • 执行一些只需执行一次的启动逻辑
  • 特点:

特性 说明
执行时机 依赖注入完成后立即执行(在构造函数之后,afterPropertiesSet() 之前)
执行次数 每个 Bean 实例只执行一次(即使它是 prototype)
异常处理 如果方法抛出异常,Bean 创建失败,Spring 启动会中断
方法要求 必须是 无参方法非静态返回 void

  那么我们可以把上述Client的初始化修改为如下,就不会发生这样的问题了。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Service
public class FeishuServiceImpl implements FeishuService {
@Value("${feishu.appId}")
private String appId;
@Value("${feishu.appSecret}")
private String appSecret;
// 构建client
private Client client;
@PostConstruct
public void init() {
this.client = Client.newBuilder(appId, appSecret).build();
}
}

  好了拜拜

  • 标题: 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 进行许可。