SpringBoot实现多个ApplicationRunner时部分接口未执行问题

SpringBoot多个ApplicationRunner时部分接口未执行

在springboot的项目中,需要在容器启动之后执行一些操作。springboot提供了ApplicationRunner和CommandLineRunner两个接口可以帮助我们实现这种需求。

当项目中实现了多个ApplicationRunner接口,并且其中一个使用了类似于while(true)这样不会退出的循环体。将会导致后续的ApplicationRunner接口不会被调用。

如下:

  1. @Component
  2. @Slf4j
  3. public class RunnerTest1 implements ApplicationRunner {
  4.      @Override
  5.      public void run(ApplicationArguments args) throws Exception {
  6.          while (true) {
  7.              System.out.println(“this is RunnerTest1”);
  8.              Thread.sleep(100);
  9.          }
  10.      }
  11. }
  1. @Component
  2. @Slf4j
  3. public class RunnerTest2 implements ApplicationRunner {
  4.      @Override
  5.      public void run(ApplicationArguments args) throws Exception {
  6.          while (true) {
  7.              System.out.println(“this is RunnerTest2”);
  8.              Thread.sleep(100);
  9.          }
  10.      }
  11. }

输出结果:

-1

可以看到项目启动后RunnerTest2 将不会被执行。

通过分析springboot启动的源码可以发现,在applicationContext容器加载完成之后,会调用SpringApplication类的callRunners方法

-2

该方法中会获取所有实现了ApplicationRunner和CommandLineRunner的接口bean,然后依次执行对应的run方法,并且是在同一个线程中执行。

因此如果有某个实现了ApplicationRunner接口的bean的run方法一直循环不返回的话,后续的代码将不会被执行。

ApplicationRunner实现项目启动就执行的功能

ApplicationRunner

是一个接口,常用于项目启动后,(也就是ApringApplication.run()执行结束),立马执行某些逻辑。

可用于项目的准备工作,比如加载配置文件,加载执行流,定时任务等等。

如何使用ApplicationRunner

这里有几点说明:

  • 1:这个实现类,要注入到spring容器中,这里使用了@Component注解;
  • 2:在同一个项目中,可以定义多个ApplicationRunner的实现类,他们的执行顺序通过注解@Order注解或者再实现Ordered接口来实现。
  • 3:run方法的参数:ApplicationArguments可以获取到当前项目执行的命令参数。(比如把这个项目打成jar执行的时候,带的参数可以通过ApplicationArguments获取到);
  • 4:由于该方法是在容器启动完成之后,才执行的,所以,这里可以从spring容器中拿到其他已经注入的bean。

(可以有多个实例实现该接口,但是一般需要增加注解@Order来指定加载顺序)

  1. @Component
  2. @Order(2)
  3. public class JDDRunner implements ApplicationRunner {
  4.      @Override
  5.      public void run(ApplicationArguments args) throws Exception {
  6.      System.out.println(args);
  7.      System.out.println(“这个是测试ApplicationRunner接口”);
  8.      }
  9. }

实现ApplicationRunner接口,重写run方法,定义具体的执行逻辑

@Order注解,用于决定多个bean的执行顺序,按照值从小到大执行 (值可为负数)

  • @Order(-1)优先于@Order(0)
  • @Order(1)优先于@Order(2)

还有个接口

也可以实现和ApplicationRunner一样的功能

  • CommandLineRunner
  • CommandLineRunner接口的run方法接收的参数为String数组

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

标签

发表评论