Spring Boot 2升级3后ApplicationPreparedEvent未触发问题咨询
在将Spring Boot 2应用升级至Spring Boot 3后,原测试用例中通过ApplicationListener监听ApplicationPreparedEvent准备测试数据的逻辑失效:Bean被创建,但onApplicationEvent方法未触发,改用@EventListener注解也无效,切换为监听ApplicationStartedEvent则恢复正常。原代码示例如下:
@ExtendWith(SpringExtension.class) @ComponentScan(basePackages = "...") @Import(TestConfig.class) @DataJpaTest @ActiveProfiles("Testprofile") public class Test { @Test public void test() {...} } @TestConfiguration @Profile("Testprofile") class TestConfig { @Bean public ApplicationListener<ApplicationPreparedEvent> setupBean() {...} }
这是Spring Boot 3的预期变更,核心原因在于Spring Boot 3对应用启动事件模型和上下文初始化流程做了调整:
事件触发时机的调整
ApplicationPreparedEvent原本是在SpringApplication完成配置加载、准备创建应用上下文后发送,但在Spring Boot 3中,该事件仅在完整的SpringApplication启动流程中触发;而@DataJpaTest这类切片测试采用轻量化上下文初始化路径,不会触发该事件的发送逻辑。启动事件模型的优化
Spring Boot 3重新梳理了启动阶段事件的职责,ApplicationPreparedEvent更偏向完整应用启动前的准备环节,切片测试、部分生产场景的上下文初始化不再依赖该事件。相反,ApplicationStartedEvent在应用上下文刷新完成、所有Bean初始化完成后发送,覆盖了包括切片测试在内的更多场景,更适合执行测试数据准备这类需要上下文就绪后的操作。上下文初始化路径的差异
Spring Boot 2中切片测试的上下文初始化会走完整的SpringApplication启动逻辑分支,因此会触发ApplicationPreparedEvent;但Spring Boot 3为优化切片测试启动速度,简化了上下文初始化流程,跳过了该事件的触发步骤。
建议后续统一使用ApplicationStartedEvent或者ContextRefreshedEvent替代,这两个事件在Spring Boot 3的各类场景(包括切片测试、生产环境)中都能稳定触发,满足测试数据准备的需求。
内容的提问来源于stack exchange,提问作者Jonathan

