【问题标题】:Different ways to run custom code before the application starts在应用程序启动之前运行自定义代码的不同方法
【发布时间】:2019-06-13 09:38:43
【问题描述】:

您能否描述在应用程序启动以进行数据初始化或其他操作之前运行自定义代码的不同方法? (如ApplicationListenerCommandLineRunner 等)

它们之间有什么区别?在哪种情况下使用它们更好? 我不仅想知道一种方法来做到这一点,而且还想知道何时以及需要使用什么。

这是一个足够老的问题,有太多选项可以做到这一点:Running code after Spring Boot starts

如果问这个问题的地方不对,请指出正确的地方。

【问题讨论】:

    标签: spring spring-boot


    【解决方案1】:

    我知道哪些选项:

    1. CommandLineRunner - 以字符串形式接收命令行参数

      @Slf4j
      @Component
      public class DemoCommandLineRunner implements CommandLineRunner {
      
          @Override
          public void run(String... args) {
              log.info("[CommandLineRunner] Args: " + Arrays.toString(args));
          }
      }
      
    2. ApplicationRunner - 接收带有名称的命令行参数

      @Slf4j
      @Component
      public class DemoApplicationRunner implements ApplicationRunner {
      
          @Override
          public void run(ApplicationArguments args) {
              log.info("[ApplicationRunner] Args: ");
              nonOptionArgs(args);
              optionArgs(args);
          }
      
          private void nonOptionArgs(ApplicationArguments args) {
              args.getNonOptionArgs().forEach(log::info);
          }
      
          private void optionArgs(ApplicationArguments args) {
              args.getOptionNames().stream()
                      .map(args::getOptionValues)
                      .map(Objects::toString)
                      .forEach(log::info);
          }
      }
      
    3. ApplicationListener - 不同事件的监听器(每个事件都有自己的类)

      @Slf4j
      @Component
      public class DemoApplicationListener implements ApplicationListener<ApplicationEvent> {
      
          @Override
          public void onApplicationEvent(ApplicationEvent event) {
              logEvent(event);
          }
      
          private void logEvent(ApplicationEvent event) {
              log.info("[DemoApplicationListener] Event: " + event);
          }
      }
      
    4. @EventListener - 不同事件的监听器(一个 bean 中的多个事件)

      @Slf4j
      @Component
      public class DemoEventApplicationListener {
      
          @EventListener
          public void handleContextRefreshedEvent(ContextRefreshedEvent event) {
              logEvent(event);
          }
      
          @EventListener
          public void handleApplicationReadyEvent(ApplicationReadyEvent event) {
              logEvent(event);
          }
      
          private void logEvent(ApplicationEvent event) {
              log.info("[DemoEventApplicationListener] Event: " + event);
          }
      }
      
    5. SmartLifecycle - 配置 bean 生命周期

      @Slf4j
      @Component
      public class DemoSmartLifecycle implements SmartLifecycle {
      
          private boolean isRunning;
      
          @Override
          public void start() {
              isRunning = true;
              log.info("[DemoSmartLifecycle]: Start");
          }
      
          @Override
          public void stop() {
              isRunning = false;
              log.info("[DemoSmartLifecycle]: Stop");
          }
      
          @Override
          public boolean isRunning() {
              return isRunning;
          }
      }
      
    6. SmartInitializingSingleton - 在单例预实例化阶段结束时触发

      @Slf4j
      @Component
      public class DemoSmartInitializingSingleton implements SmartInitializingSingleton {
      
          @Override
          public void afterSingletonsInstantiated() {
              log.info("[SmartInitializingSingleton] afterSingletonsInstantiated");
          }
      }
      

    Github 仓库:https://github.com/venkaDaria/demo-bootstrap-spring

    【讨论】:

      【解决方案2】:

      如果您需要在“SpringApplication 启动后”运行一些代码,您应该使用ApplicationRunnerCommandLineRunner - 它们可以工作the same way

      ApplicationListener@EventListenerApplicationReadyEvent 也可以这样做。

      见我的example

      您选择的选项取决于您。

      【讨论】:

      • SmartLifecycle等方式呢?那么,这仅取决于我的喜好吗?
      • @DariaPydorenko 我没有使用它。但我认为 SmartLifecycle 比其他人更适合 bit more redundant option,如果您只需要“在 SpringApplication 启动后”运行一些代码。
      猜你喜欢
      • 2021-08-11
      • 2023-03-20
      • 2015-10-05
      • 2018-08-09
      • 2016-12-31
      • 2013-05-19
      • 2013-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多