文章目录
- 理论基础
- 1. `@PostConstruct` 注解(最早执行)
- 2. `InitializingBean` 接口
- 3. `@Bean(initMethod)` 指定的方法
- 4. `SmartLifecycle` 接口(phase <=0 的部分)
- 5. `ApplicationContext` 事件监听器(`ContextRefreshedEvent`)
- 6. `SmartLifecycle` 接口(phase >0 的部分)
- 7. `ApplicationRunner` 接口
- 8. `CommandLineRunner` 接口
- 9. `ApplicationReadyEvent` 事件监听器
- 10. `SpringApplication.run()` 之后手动代码(最晚执行)
- 使用建议
理论基础
首先我们要明确SpringBoot启动的生命周期:
1. 启动SpringApplication
2. 初始化ApplicationContext,加载Bean定义
3. 实例化单例Bean(非延迟)并初始化:
3.1 依赖注入
3.2 调用BeanPostProcessor的postProcessBeforeInitialization
3.3 调用@PostConstruct方法
3.4 调用InitializingBean的afterPropertiesSet方法
3.5 调用自定义initMethod方法
3.6 调用BeanPostProcessor的postProcessAfterInitialization
4. 启动SmartLifecycle(phase<=0的部分,默认phase为0):
4.1 按照phase从小(可以是负数)到大(0)的顺序执行start()
5. 发布ContextRefreshedEvent事件
6. 启动SmartLifecycle(phase值大于0的部分):
6.1 按照phase从小(大于0)到大(正整数)的顺序执行start()
7. 执行所有的ApplicationRunner和CommandLineRunner(提问: 固定先ApplicationRunner后CommandLineRunner吗?不是,首先根据@Order排序,如果@Order一样则先执行ApplicationRunner,再执行CommandLineRunner. 例如: CommandLineRunner(Order=1) --> ApplicationRunner(Order=2) --> CommandLineRunner(Order=2))
8. 发布ApplicationReadyEvent
9. 启动完成
因此我们有以下10种方法可以使用
1. @PostConstruct
注解(最早执行)
-
执行时机:Bean 初始化期间(依赖注入完成后)
-
特点:
- 只作用于当前 Bean
- 同一个类中多个
@PostConstruct
方法执行顺序不确定
-
示例:
@Component public class InitBean { @PostConstruct public void init() { System.out.println("1. @PostConstruct 执行"); } }
2. InitializingBean
接口
-
执行时机:Bean 初始化期间(在
@PostConstruct
之后) -
方法:实现
afterPropertiesSet()
-
示例:
@Component public class MyBean implements InitializingBean { @Override public void afterPropertiesSet() { System.out.println("2. InitializingBean 执行"); } }
3. @Bean(initMethod)
指定的方法
-
执行时机:Bean 初始化期间(在
InitializingBean
之后) -
示例:
@Configuration public class AppConfig { @Bean(initMethod = "init") public MyService myService() { return new MyService(); } } public class MyService { public void init() { System.out.println("3. @Bean initMethod 执行"); } }
4. SmartLifecycle
接口(phase <=0 的部分)
-
方法:实现
start()
方法 -
特点:可以控制启动/停止顺序(通过
getPhase()
返回值) -
示例:
@Component public class LifecycleBean implements SmartLifecycle { private boolean running = false; @Override public void start() { running = true; System.out.println("4. SmartLifecycle 启动"); } @Override public int getPhase() { return -1; // 值越小越早启动 } }
5. ApplicationContext
事件监听器(ContextRefreshedEvent
)
-
执行时机:在所有 Bean 初始化完成后,应用启动过程中
-
特点:可以访问完整的 Bean 集合
-
示例:
@Component public class ContextListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("5. ContextRefreshedEvent 监听器执行"); } }
6. SmartLifecycle
接口(phase >0 的部分)
7. ApplicationRunner
接口
-
执行时机:应用完全启动后(在所有 Bean 初始化和
ContextRefreshedEvent
之后) -
特点:可以使用
@Order
指定多个 Runner 的执行顺序 -
示例:
@Component @Order(1) public class AppRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) { System.out.println("7. ApplicationRunner 执行 (Order=1)"); } }
8. CommandLineRunner
接口
-
执行时机:与
ApplicationRunner
同时期,但在相同@Order
值下晚于ApplicationRunner
-
特点:接收原始命令行参数
-
示例:
@Component @Order(1) public class CmdRunner implements CommandLineRunner { @Override public void run(String... args) { System.out.println("8. CommandLineRunner 执行 (Order=1)"); } }
相同
@Order
时的执行顺序:
ApplicationRunner
→CommandLineRunner
9. ApplicationReadyEvent
事件监听器
@Component
public class OnAppReady {
@EventListener(ApplicationReadyEvent.class)
public void onReady() {
System.out.println("9. ApplicationReadyEvent监听器执行, 应用完全就绪,安全执行启动任务");
// 可安全访问数据库和其他外部服务
}
}
10. SpringApplication.run()
之后手动代码(最晚执行)
-
执行时机:在应用完全启动后(所有组件初始化完成后)
-
示例:
public class Application { public static void main(String[] args) { ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args); System.out.println("10. SpringApplication.run() 后手动代码执行"); } }
使用建议
- 核心业务初始化 → 使用
ApplicationReadyEvent
- 耗时长任务 → 添加
@Async
和超时控制 - 全局启动任务:
- 简单任务 →
CommandLineRunner
- 需参数解析 →
ApplicationRunner
- 需要启停控制 →
SmartLifecycle
- 简单任务 →
- 最后执行任务:在
main
方法中SpringApplication.run()
后添加逻辑