『深入学习 Spring Boot』(九) 启动加载器

529 阅读2分钟

前言

前面我们学习了非常重要 refresh 方法以及 Bean 的实例化过程,我们根据 run 方法来看,下一步就是该学习启动加载器了。

public ConfigurableApplicationContext run(String... args) {
    ......
        callRunners(context, applicationArguments);
    ......
}

其中 callRunners(context, applicationArguments)方法,就是去调用了启动加载器。

经过我们前面的学习,这一节的源码应该看起来是不怎么费劲的。

启动加载器

启动加载器一般用于,应用程序启动以后,需要立马做些什么事情时。

实践方式

启动加载器有两种实现方式:CommandLineRunner ApplicationRunner接口。

实现 CommandLineRunner 接口

@Component
public class MyOneRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("我的第一个启动加载器");
    }
}

实现 ApplicationRunner 接口

@Component
public class MyTwoRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("我的第二个启动加载器");
    }
}

打印结果

image-20210522162111716

欸,看到这里,就有一点问题了,为什么MyTwoRunner会先于MyOneRunner打印呢?

然后我们使用@Order()注解:@Oder(11)MyTwoRunner@Order(10)MyOneRunner

image-20210522162530385

这次执行顺序又有所改变了,我们带着这些问题,去学习一下相关的源码。

启动加载器原理

private void callRunners(ApplicationContext context, ApplicationArguments args) {
        List<Object> runners = new ArrayList<>();
        // 获取容器中 ApplicationRunner 类型的 Bean
        runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
        // 获取容器中 CommandLineRunner 类型的 Bean
        runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
         // 排序
        AnnotationAwareOrderComparator.sort(runners);
         // 分别执行 ApplicationRunner、CommandLineRunner 的 run 方法体
        for (Object runner : new LinkedHashSet<>(runners)) {
            if (runner instanceof ApplicationRunner) {
                callRunner((ApplicationRunner) runner, args);
            }
            if (runner instanceof CommandLineRunner) {
                callRunner((CommandLineRunner) runner, args);
            }
        }
    }

嘿嘿,经过前面的学习,这些逻辑体,我们一眼都能看出来是在干嘛了。

虽然是比较简单的功能逻辑,但也有一点小小的成就感了。

在没有@Order注解的时候,是填添加的 ApplicationRunner,后添加的 CommandLineRunner,所以在无@Order注解情况下,是先执行 ApplicationRunner。

又因为都添加到 runners 集合中后,执行了排序方法,所以我们添加的@Order方法才会生效。

总结

这一小节的东西比较简单,主要了解一下 Spring Boot 有这么个东西,简单翻阅一下源码。