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
相关产品推荐
相关产品推荐

