【SpringBoot】给你的 CommandLineRunner 排个序

197 阅读1分钟

本文演示如何给 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);
			}
		}
	}

最后还是那句话,多看源码。