美文网首页
SpringBoot源码剖析之ApplicationRunner

SpringBoot源码剖析之ApplicationRunner

作者: 我有一只喵喵 | 来源:发表于2020-03-19 22:18 被阅读0次

    一、ApplicationRunner、CommandLineRunner是什么?可以用来干嘛

    ApplicationRunner、CommandLineRunner均为两个接口,均包含一个run方法,当用户实现了上述两接口之后,如果注册为bean,则其run方法将在容器启动之后执行。

    二、如何使用

    2.1 实现ApplicationRunner、CommandLineRunner接口,并重写run方法

    
    @Component
    
    public class CustomApplicationRunner implements ApplicationRunner {
    
        @Override
    
        public void run(ApplicationArguments args) throws Exception {
    
            System.out.println("i am CustomApplicationRunner");
    
            args.getOptionNames().stream().forEach(option -> System.out.println(args.getOptionValues(option)));
    
        }
    
    }
    
    
    
    @Component
    
    public class CustomCommonLineRunner implements CommandLineRunner {
    
        @Override
    
        public void run(String... args) throws Exception {
    
            System.out.println("i am CustomCommonLineRunner");
    
            for (String arg : args) {
    
                System.out.println(arg);
    
            }
    
        }
    
    }
    
    

    2.2 设置容器启动参数 --key=value

    image

    2.3 如果存在ApplicationRunner的多个实现类或者存在CommandLineRunner的多个实现类,他们的执行顺序可以使用@Order注解进行指定

    三、源码解读

    当执行SpringApplication.run(XXXApplication.class, args);启动应用时,其run方法相应的实现如下

    SpringApplication.run

    
    public ConfigurableApplicationContext run(String... args) {
    
    ...
    
     try {
    
         //将启动参数封装为ApplicationArguments
    
     ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    
         ....
    
         //准备上下文
    
     context = createApplicationContext();
    
         ...
    
     //传入上下文,以及入参对象调用runner
    
     callRunners(context, applicationArguments);
    
     }
    
     catch (Throwable ex) {
    
     handleRunFailure(context, ex, exceptionReporters, listeners);
    
     throw new IllegalStateException(ex);
    
     }
    
     try {
    
     listeners.running(context);
    
     }
    
     catch (Throwable ex) {
    
     handleRunFailure(context, ex, exceptionReporters, null);
    
     throw new IllegalStateException(ex);
    
     }
    
     return context;
    
    }
    
    

    SpringApplication.callRunners

    
    private void callRunners(ApplicationContext context, ApplicationArguments args) {
    
       //runner列表
    
     List<Object> runners = new ArrayList<>();
    
     //添加所有ApplicationRunner类型的bean到runner列表
    
     runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    
     //添加所有CommandLineRunner类型的Bean到runner列表
    
     runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    
     //将runner列表排序
    
     AnnotationAwareOrderComparator.sort(runners);
    
     for (Object runner : new LinkedHashSet<>(runners)) {
    
         //遍历执行
    
     if (runner instanceof ApplicationRunner) {
    
       callRunner((ApplicationRunner) runner, args);
    
     }
    
     if (runner instanceof CommandLineRunner) {
    
       callRunner((CommandLineRunner) runner, args);
    
     }
    
     }
    
    }
    
    private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
    
     try {
    
     (runner).run(args);
    
     }
    
     catch (Exception ex) {
    
     throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
    
     }
    
    }
    
    private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
    
     try {
    
     (runner).run(args.getSourceArgs());
    
     }
    
     catch (Exception ex) {
    
     throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
    
     }
    
    }
    
    

    到这里我们已经明白了springboot是如何在容器启动之后执行两种runner的run方法。仔细观察callRunners中的AnnotationAwareOrderComparator.sort(runners)方法,该方法决定了各个runner的执行顺序,查看源码

    
    public static void sort(List<?> list) {
    
     if (list.size() > 1) {
    
     list.sort(INSTANCE);
    
     }
    
    }
    
    

    其中INSTANCE为AnnotationAwareOrderComparator,该比较器就是Spring提供通过@Order指定顺序的支持。关于该类的工作原理见下回分解。

    相关文章

      网友评论

          本文标题:SpringBoot源码剖析之ApplicationRunner

          本文链接:https://www.haomeiwen.com/subject/ohvryhtx.html