如何在SpringBoot启动时执行特定代码

在SpringBoot的项目中,经常会遇到需要在项目启动后执行一些操作的情形,如加载配置,初始化数据,缓存预热等,本文整理了几种常见的在项目启动时执行特定代码的方法。

1.使用 @PostConstruct 注解

@Slf4j
@Component
public class MyInit {

    @PostConstruct
    public void init() {
        log.info("PostConstruct initialized~~~");
    }

}

优点:

  • 简单直接:只需在方法上添加 @PostConstruct 注解,方法会在Bean初始化后立即执行。
  • 灵活性高:可以在任何Bean中使用,适合对特定Bean进行初始化逻辑。

缺点:

  • 无法控制执行顺序:多个 @PostConstruct 方法的执行顺序不可控。
  • 不适合复杂启动逻辑:在Bean初始化完成后执行,但此时可能其他Bean尚未完全初始化完成,不适合依赖其他Bean的复杂场景。

2.使用 CommandLineRunner 接口

CommandLineRunner 接口提供了一个 run 方法,该方法会在Spring Boot应用启动后执行。

@Component
@Slf4j
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info("MyStartupRunner CommandLineRunner initialized~~~");
    }
}

优点:

  • 简单易用:实现 CommandLineRunner 接口并重写 run 方法即可。
  • 适合处理命令行参数:可以直接访问命令行参数(String… args)。
  • 顺序可控:可以通过 @Order 注解或实现 Ordered 接口来控制多个 CommandLineRunner 的执行顺序。

缺点:

  • 执行时机较早:在Spring应用上下文刷新完成后执行,但此时可能某些Bean尚未完全初始化完成,不适合依赖某些复杂Bean的场景。

3.使用 ApplicationRunner 接口

ApplicationRunner 接口与 CommandLineRunner 类似,但它提供了更丰富的 ApplicationArguments 参数来处理命令行参数。

@Slf4j
@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("MyApplicationRunner initialized~~~");
    }
}

优点:

  • 更强大的参数处理:提供了 ApplicationArguments 对象,可以更方便地解析命令行参数(如 --key=value 格式)。
  • 顺序可控:同样可以通过 @Order 注解或实现 Ordered 接口来控制执行顺序。

缺点:

  • 执行时机较早:与CommandLineRunner类似,可能某些Bean尚未完全初始化完成,不适合依赖某些复杂Bean的场景。

4.使用 ApplicationListener 监听 ApplicationReadyEvent

@Component
@Slf4j
public class MyApplicationListener implements ApplicationListener<ApplicationReadyEvent> {
    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        log.info("MyApplicationListener initialized~~~");
    }
}

优点:

  • 确保应用完全启动ApplicationReadyEvent 是在应用完全启动后触发的,适合执行依赖其他Bean或外部资源的逻辑。
  • 灵活性强:可以监听其他Spring事件(如 ContextRefreshedEvent),适合更复杂的场景。

缺点:

  • 无法直接访问命令行参数:如果需要处理命令行参数,需要额外处理。

5.@EventListener监听ApplicationReadyEvent

可以使用 @EventListener 注解来监听 ApplicationReadyEvent 事件

@Component
@Slf4j
public class MyEventListener {
    @EventListener(ApplicationReadyEvent.class)
    public void onApplicationReady() {
        log.info("MyEventListener initialized~~~");
    }
}

优点:

  • 简洁:使用注解方式监听事件,代码更简洁。
  • 确保应用完全启动:与 ApplicationListener 相同,适合在应用完全启动后执行逻辑。
  • 灵活性强:可以监听多个事件。

缺点:

  • 无法直接访问命令行参数:同样需要额外处理命令行参数。
  • 执行顺序不可控:多个监听器的执行顺序不可控。

以上几种方式执行后日志打印如下:

[main] com.example.springdemo.init.MyInit       : PostConstruct initialized~~~
[main] c.e.springdemo.SpringDemoApplication     : Started SpringDemoApplication in 0.358 seconds (JVM running for 0.809)
[main] c.e.springdemo.init.MyApplicationRunner  : MyApplicationRunner initialized~~~
[main] c.e.springdemo.init.MyCommandLineRunner  : CommandLineRunner initialized~~~
[main] c.e.s.init.MyApplicationListener         : MyApplicationListener initialized~~~
[main] c.e.springdemo.init.MyEventListener      : MyEventListener initialized~~~

总结

  • 如果需要处理命令行参数,优先选择 CommandLineRunnerApplicationRunner
  • 如果只是简单的Bean初始化逻辑,使用 @PostConstruct
  • 如果需要在应用完全启动后执行逻辑,选择 ApplicationListener@EventListener
  • 如果需要更灵活的事件监听机制,选择 ApplicationListener@EventListener

你可能感兴趣的:(技术学习,spring,boot,java)