最常用方式是实现ApplicationRunner或CommandLineRunner接口,它们在容器启动完毕、所有单例Bean初始化完成后执行;其次可用@PostConstruct或InitializingBean监听单个Bean初始化;还可监听ContextRefreshedEvent事件,但需判别根上下文。

在 Spring 中,可以通过监听容器生命周期事件来感知 Bean 初始化完成的时机。最常用、最直接的方式是实现 ApplicationRunner 或 CommandLineRunner 接口,它们会在 Spring 容器启动完毕、所有单例 Bean 初始化完成后被调用。
使用 ApplicationRunner 监听初始化完成
ApplicationRunner 是 Spring Boot 提供的回调接口,其 run 方法会在 ApplicationContext 加载完成、所有 Bean 实例化和依赖注入完成后执行,且支持参数注入(如 ApplicationArguments)。
- 实现该接口的 Bean 会被自动注册为容器中的普通 Bean
- 多个 Runner 可通过 @Order 注解或实现 Ordered 接口控制执行顺序
- 适合执行启动后的一次性逻辑,比如预热缓存、校验配置、连接外部服务等
@Component
@Order(1)
public class MyStartupRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("所有 Bean 初始化完成,应用已就绪");
// 此处可安全调用其他 Bean 的方法
}
}
使用 InitializingBean 或 @PostConstruct(针对单个 Bean)
如果只需监听某个特定 Bean 自身的初始化完成,而非整个容器,推荐使用更轻量级的方式:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- @PostConstruct:标注在方法上,由 JSR-250 规范定义,在依赖注入完成后、任何其他初始化逻辑前执行
- InitializingBean.afterPropertiesSet():Spring 原生接口,语义明确,但耦合框架 API
- 二者均不适用于跨 Bean 协作场景,仅保证当前 Bean 初始化流程结束
监听 ContextRefreshedEvent(全局容器事件)
ApplicationContext 刷新完成时(即 refresh() 方法执行完毕),会发布 ContextRefreshedEvent。可通过 @EventListener 注解监听该事件:
立即学习“Java免费学习笔记(深入)”;
- 适用于需要响应容器整体就绪状态的组件,如监控埋点、动态注册端点
- 注意:在双上下文环境(如 Spring MVC + Root Context)中,该事件可能触发多次
- 建议配合条件判断(如 event.getApplicationContext().getParent() == null)确保只处理根上下文
@Component
public class ContextReadyListener {
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
if (event.getApplicationContext().getParent() == null) {
System.out.println("根容器刷新完成,所有 Bean 初始化就绪");
}
}
}
避免常见误区
以下方式不适合用于监听“Bean 初始化完成”:
- @Bean(initMethod = "..."):仅对当前 Bean 生效,无法感知其他 Bean 状态
- 构造函数或 setter 注入中执行逻辑:此时依赖可能尚未注入,或目标 Bean 尚未创建
- 实现 SmartLifecycle 并设置 autoStartup = true:它关注的是“容器启动阶段”,而非“初始化完成”,且启动时机晚于 ApplicationRunner

















