SpringBoot中CommandLineRunner的源码实现

一个简单的CommandLineRunner的使用案例

@Component
public class TestTask implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("runner");
    }
}

我们在run方法中打断点,调试以获得执行CommandLineRunner时的调用栈

我们可以看到,调用在SpringApplication类的callRunner方法中。如图:
SpringBoot中CommandLineRunner的源码实现_第1张图片
我们进入源代码,可以看到是callRunners()方法调用了callRunner
SpringBoot中CommandLineRunner的源码实现_第2张图片
我们进入到SpringApplicationrun方法,可以看到,是在容器刷新完毕(也就是所有的bean都创建完成了)之后,结合callRunners方法分析,ApplicationRunnerCommandLineRunner都直接从容器中通过容器的getBeansOfType方法获取的,然后两种Runner被放到了一个ArrayList中,根据@Order 或者 @javax.annotation.Priority 注解定义的顺序进行了排序,之后混合一起的按照顺序执行。
另外,可以看到第三处,还捕获了异常,进入处理异常的这个方法会发现容器会关闭并且最终异常被重新抛出,导致应用启动失败。所以在使用Runner要注意这一点。
SpringBoot中CommandLineRunner的源码实现_第3张图片

总结

  1. 容器中的bean创建完成后,runner才被SpringApplication调用;
  2. ApplicationRunnerCommandLineRunner被放在一起,统一按照@Order@javax.annotation.Priority定义的顺序混合执行;
  3. runner中抛出的异常,会导致应用启动失败;
  4. 最后,不建议在runner中执行耗时长的任务(因为这是主线程,且后面还有步骤),建议作为触发异步任务的手段。

你可能感兴趣的:(springboot,java,源码)