
本文演示如何给 SpringBoot 工程中的多个 CommandLineRunner 排序,实现按规定顺序执行的效果。
首先假设有以下 3 个 CommandLineRunner 的实现类:
public class Runner1 implements CommandLineRunner {
public void run(String... args) throws Exception {
log.info("runner 1 running...");
}
}
public class Runner2 implements CommandLineRunner {
public void run(String... args) throws Exception {
log.info("runner 2 running...");
}
}
public class Runner3 implements CommandLineRunner {
public void run(String... args) throws Exception {
log.info("runner 3 running...");
}
}
我们想要这 3 个 runner 按照 3 -> 2 -> 1 的顺序执行,该怎么做呢?
根据 CommnadLineRunner 的源码注释(... can be ordered using the {@link Ordered} interface or {@link Order @Order} annotation. ...)的描述可知,我们可以通过给这三个 runner 类上添加 @Order 注解并指定我们想要的执行顺序来实现:
@Order(value=3)
public class Runner1 implements CommandLineRunner {
public void run(String... args) throws Exception {
log.info("runner 1 running...");
}
}
@Order(value=2)
public class Runner2 implements CommandLineRunner {
public void run(String... args) throws Exception {
log.info("runner 2 running...");
}
}
@Order(value=1)
public class Runner3 implements CommandLineRunner {
public void run(String... args) throws Exception {
log.info("runner 3 running...");
}
}
而真正在背后干活的是 SpringApplication#callRunners() 方法中的 AnnotationAwareOrderComparator.sort(runners); :
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);
}
}
}
最后还是那句话,多看源码。