You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3中如何在SpringBootTest加载上下文前执行代码

问题

在Spring Boot 3中运行如下测试代码时,发现Spring Boot的启动日志先输出,之后才执行测试类的静态代码块和@BeforeAll方法,这与Spring Boot 2.7.x中的执行顺序相反。预期是类加载时先执行静态代码,再初始化Spring上下文,请问如何在Spring Boot开始加载上下文前执行代码?

测试代码:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExampleTest {

    static {
        System.out.println("hello from static");
    }

    @BeforeAll
    static void beforeAll() {
        System.out.println("before all!");
    }

    @Test
    void contextLoads() {
        System.out.println("hello!");
    }
}
解决方案

Spring Boot 3调整了测试上下文的启动流程,测试类的加载被延迟到上下文初始化后期,导致原有的静态代码块和@BeforeAll方法无法在上下文加载前执行。要实现上下文加载前的代码执行,可以采用以下两种可靠方式:

1. 使用ApplicationContextInitializer

这是Spring提供的标准扩展点,会在上下文创建和初始化的最早期被调用,对应的类会在Spring上下文启动前被加载,因此其静态代码块或初始化逻辑会优先执行。

步骤:

  • 自定义初始化器类,实现ApplicationContextInitializer接口:
public class PreContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    // 静态代码块会在类加载时执行,早于Spring上下文启动
    static {
        System.out.println("这段代码在Spring上下文加载前执行");
    }

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // 这里可以编写上下文初始化前的自定义逻辑
        // 比如设置系统属性、加载外部配置等
    }
}
  • 在测试类上通过@ContextConfiguration指定该初始化器:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(initializers = PreContextInitializer.class)
public class ExampleTest {
    // 原测试代码保持不变
    static {
        System.out.println("hello from static");
    }

    @BeforeAll
    static void beforeAll() {
        System.out.println("before all!");
    }

    @Test
    void contextLoads() {
        System.out.println("hello!");
    }
}

2. 利用测试类的父类静态代码块

如果不需要通用的初始化逻辑,可以创建一个父类,将需要提前执行的代码放在父类的静态代码块中。由于父类会在子类(测试类)加载前被加载,其静态代码块会优先于Spring上下文启动执行:

public class PreContextTestParent {
    static {
        System.out.println("父类静态代码块,早于Spring上下文加载");
    }
}

测试类继承该父类:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ExampleTest extends PreContextTestParent {
    // 原测试代码保持不变
}

注意事项

  • 避免在提前执行的代码中依赖Spring容器的任何组件,此时上下文尚未初始化,无法获取Bean。
  • ApplicationContextInitializer适用于需要复用的全局初始化逻辑,父类静态代码块适用于单个测试类的简单场景。

内容的提问来源于stack exchange,提问作者szakal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 07:13:07