目录
一、引言
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 {
@Test
void testBiz() {
}
}
5.3 总结
AbstractTestExecutionListener
是一个便于扩展的抽象类,提供了测试执行生命周期的钩子方法,默认实现为空操作,子类可以根据需要重写这些方法以实现自定义逻辑,同时支持通过 Ordered
接口控制执行顺序。继承该类可在测试执行的不同阶段插入自定义逻辑,例如初始化资源、清理资源、记录日志等