Spring Boot 启动后执行特定代码的10种方法

理论基础

首先我们要明确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 时的执行顺序:
ApplicationRunnerCommandLineRunner


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() 后手动代码执行");
        }
    }
    

使用建议

  1. 核心业务初始化 → 使用 ApplicationReadyEvent
  2. 耗时长任务 → 添加 @Async 和超时控制
  3. 全局启动任务:
    • 简单任务 → CommandLineRunner
    • 需参数解析 → ApplicationRunner
    • 需要启停控制 → SmartLifecycle
  4. 最后执行任务:在 main 方法中 SpringApplication.run() 后添加逻辑
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值