目录
- 一、引言
- 二、核心方法概述
- 三、加载机制
- 四、使用场景
- 五、扩展 - 如何在测试的不同阶段插入逻辑
- 5.1 TestExecutionListener & AbstractTestExecutionListener
- 5.1.1 主要功能
- 5.1.2 生命周期方法
- 5.2 如何集成TestExecutionListener
- 5.3 总结
一、引言
SpringApplicationRunListener 是 Spring Boot 提供的一个接口,用于监听 SpringApplication 的运行过程。它允许开发者在 Spring Boot 应用的不同生命周期阶段插入自定义逻辑。该接口的实现类通过 SpringFactoriesLoader 加载,并且需要提供一个公共构造函数,接受 SpringApplication 实例和 String[] 参数。
二、核心方法概述
-
starting方法
starting(ConfigurableBootstrapContext bootstrapContext)方法在run方法刚开始时立即调用,用于非常早期的初始化操作。default void starting(ConfigurableBootstrapContext bootstrapContext) { } -
environmentPrepared方法
在环境准备好但ApplicationContext尚未创建之前调用。此方法可以用于在环境配置完成后执行逻辑。default void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,ConfigurableEnvironment environment) { } -
contextPrepared方法
在ApplicationContext创建并准备好,但尚未加载资源之前调用。default void contextPrepared(ConfigurableApplicationContext context) { } -
contextLoaded方法
在ApplicationContext加载完成但尚未刷新之前调用。default void contextLoaded(ConfigurableApplicationContext context) { } -
started方法
在上下文刷新后,应用启动完成,但CommandLineRunner和ApplicationRunner尚未执���时调用。default void started(ConfigurableApplicationContext context, Duration timeTaken) { } -
ready方法
在run方法即将结束时调用,此时应用上下文已刷新,所有CommandLineRunner和ApplicationRunner已执行。default void ready(ConfigurableApplicationContext context, Duration timeTaken) { } -
failed方法
如果应用启动过程中发生异常,则调用此方法。default void failed(ConfigurableApplicationContext context, Throwable exception) { }
三、加载机制
SpringApplicationRunListener 的实现类通过 SpringFactoriesLoader 加载,开发者需要在 META-INF/spring.factories (适用于SpringBoot2)或 META-INF/spring/org.springframework.boot.SpringApplicationRunListener(适用于SpringBoot3) 文件中注册实现类。
META-INF/spring.factories 示例:
org.springframework.boot.SpringApplicationRunListener=\
com.luo.MySpringApplicationRunListener
META-INF/spring/org.springframework.boot.SpringApplicationRunListener示例:
com.luo.MySpringApplicationRunListener
四、使用场景
该接口适用于需要在 Spring Boot 启动的不同阶段插入自定义逻辑的场景,例如日志记录、环境配置或启动监控等。
我的使用场景是在SpringBoot启动前执行一些扩展逻辑,所以只是重写了SpringApplicationRunListener.starting方法,但是在starting方法通过org.slf4j.Logger打印的日志没有正常显示(由于starting阶段日志框架没有加载完成),所以又单独做了个日志打印工具,在starting阶段调用日志工具时将日志内容缓存起来,之后在contextPrepared方法中统一对缓存的日志进行打印,当然你也可以直接System.out.println进行打印…
五、扩展 - 如何在测试的不同阶段插入逻辑
5.1 TestExecutionListener & AbstractTestExecutionListener
AbstractTestExecutionListener 是 Spring 框架中一个抽象类,位于 org.springframework.test.context.support 包下。它实现了 TestExecutionListener 和 Ordered 接口,主要用于在测试执行过程中提供扩展点。以下是对该类的详细说明:
5.1.1 主要功能
-
实现
Ordered接口:- 提供了
getOrder()方法,默认返回Ordered.LOWEST_PRECEDENCE,表示该监听器的执行顺序优先级最低。 - 子类可以重写此方法以调整执行顺序。
- 提供了
-
实现
TestExecutionListener接口:- 提供了多个生命周期方法(如
beforeTestClass、afterTestMethod等),这些方法在测试执行的不同阶段被调用。 - 默认实现是空操作(
no-op),子类可以根据需要重写这些方法以添加自定义逻辑。
- 提供了多个生命周期方法(如
5.1.2 生命周期方法
以下是 TestExecutionListener 接口中定义的生命周期方法及其默认实现:
beforeTestClass:在测试类执行前调用,默认无操作。prepareTestInstance:在测试实例准备好后调用,默认无操作。beforeTestMethod:在每个测试方法执行前调用,默认无操作。beforeTestExecution:在测试方法执行前调用(从 Spring 5.2 开始),默认无操作。afterTestExecution:在测试方法执行后调用(从 Spring 5.2 开始),默认无操作。afterTestMethod:在每个测试方法执行后调用,默认无操作。afterTestClass:在测试类执行后调用,默认无操作。
5.2 如何集成TestExecutionListener
通过@TestExecutionListeners.listeners引用自定义的TestExecutionListener实现类:
@SpringBootTest
@TestExecutionListeners(listeners = MyTestExecutionListener.class, mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS
)
public class MyTest {@Testvoid testBiz() {}
}
5.3 总结
AbstractTestExecutionListener 是一个便于扩展的抽象类,提供了测试执行生命周期的钩子方法,默认实现为空操作,子类可以根据需要重写这些方法以实现自定义逻辑,同时支持通过 Ordered 接口控制执行顺序。继承该类可在测试执行的不同阶段插入自定义逻辑,例如初始化资源、清理资源、记录日志等