什么是启动类加载器
就是SpringBoot启动后,要立马执行的程序,这时候就需要启动类加载器完整这个要求。
启动类加载器实践
1、创建第一个启动类加载器(方式1)
1)、创建启动类加载器,实现CommandLineRunner接口
@Component
public class FirstCommandlineRunner implements CommandLineRunner{
@Override
public void run(String... args) throws Exception {
System.out.println("\u001B[32m >>> startup fist runner<<<");
}
}
2)、启动项目,输出如下
2、多个类加载器,如何控制调用顺序。
只需要增加Order注解即可
第一个启动类加载器
@Component
@Order(1)
public class FirstCommandlineRunner implements CommandLineRunner{
@Override
public void run(String... args) throws Exception {
System.out.println("\u001B[32m >>> startup fist runner<<<");
}
}
第二个启动类加载器
@Component
@Order(2)
public class SecondCommandlineRunner implements CommandLineRunner{
@Override
public void run(String... args) throws Exception {
System.out.println("\u001B[32m >>> startup second runner<<<");
}
}
然后启动项目,输出如下
2、创建类加载器,方式二
1)、创建FirstApplicationRunner 类,实现 ApplicationRunner接口,然后设置Order为1
@Component
@Order(1)
public class FirstApplicationRunner implements ApplicationRunner{
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("\u001B[32m >>> startup first application runner<<<");
}
}
- 同理,创建SecondApplicationRunner 类,实现 ApplicationRunner接口,然后设置Order为2
@Component
@Order(2)
public class SecondApplicationRunner implements ApplicationRunner{
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("\u001B[32m >>> startup second application runner<<<");
}
}
3)启动项目,查看输出结果如下
3、启动类加载器原理
进入run方法,启动类加载器的入口是callRunners方法
进入callRunners方法
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
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);
}
}
}
将实现ApplicationRunner接口的类实例增加到runners列表中
将实现CommandLineRunner接口的类实例增加到runners列表中。
然后进行排序AnnotationAwareOrderComparator.sort(runners);
排序完毕后依次调用callRunner方法
callRunner方法实现如下。里面调用各自的run方法
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);
}
}