使用启动加载器
实现CommandLineRunner 接口
@Order(1)
@Component
public class FirstCommandlineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("=========FirstCommandlineRunner=============");
}
}
实现ApplicationRunner 接口
@Order(1)
@Component
public class SecondApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("=========SecondApplicationRunner=============");
}
}
两种实现方式比较
相同点
-
调用点一样
都是在callRunners中调用 -
实现方法名一样
都是通过实现接口来重写run方法 -
通过Order来决定实现顺序
差异点
- 执行优先级差异,第二种 > 第一种
- run方法入参不一致
CommandLineRunner 实现run传入String… args
ApplicationRunner 实现run传入ApplicationArguments args
执行结果
有执行结果可以看出,两种实现方式的Order一样,但是第二种的执行顺序早于第一种执行顺序,为什么会是这样的执行顺序,继续往下看
原理解析
run()方法中调用: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和CommandLineRunner接口的实现类,然后对runners进行排序,排序后遍历调用执行callRunner方法
- List runners = new ArrayList<>(); 用的是object来装所有的Runner,在排序的时候对两种实现都采用Order注解排序,所以会对两种实现方式基于Order来排序
- 上面的两种实现方式,由于Order值一样都是1,但是runners.addAll()是添加ApplicationRunner接口实现对象,runners是个有序集合,所以第二种的执行顺序早于第一种
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);
}
}