前言
前面我们学习了非常重要 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("我的第二个启动加载器");
}
}
复制代码
打印结果
欸,看到这里,就有一点问题了,为什么MyTwoRunner
会先于MyOneRunner
打印呢?
然后我们使用@Order()
注解:@Oder(11)MyTwoRunner
、@Order(10)MyOneRunner
:
这次执行顺序又有所改变了,我们带着这些问题,去学习一下相关的源码。
启动加载器原理
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 有这么个东西,简单翻阅一下源码。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END