Java ApplicationRunner与CommandLineRunner
我刚接触Spring boot,并阅读了有关ApplicationRunner和CommandLineRunner的信息。两者功能相同。当我同时实现两个接口时,总是先运行CommandLineRunner的方法,然后再运行ApplicationRunner的方法Java ApplicationRunner与CommandLineRunner,java,spring-boot,Java,Spring Boot,我刚接触Spring boot,并阅读了有关ApplicationRunner和CommandLineRunner的信息。两者功能相同。当我同时实现两个接口时,总是先运行CommandLineRunner的方法,然后再运行ApplicationRunner的方法 任何人都可以提供帮助,为什么CommandLineRunner的方法优先于ApplicationRunner的方法。好吧,我认为在任何情况下都不需要同时实现这两个接口 这两种方法在实现时都表示应在应用程序启动时调用run方法 Appli
任何人都可以提供帮助,为什么CommandLineRunner的方法优先于ApplicationRunner的方法。好吧,我认为在任何情况下都不需要同时实现这两个接口 这两种方法在实现时都表示应在应用程序启动时调用
run
方法
ApplicationRunner
和CommandLineRunner
之间的区别在于,在ApplicationRunner
上,不是传递给run
方法的原始字符串参数,我们有一个ApplicationArguments
的实例,这样您就可以访问初始化应用程序时传递的引导参数
使用CommandLineRunner
您也可以访问它们,但作为原始字符串参数,因此您必须自己解析它们
您可以自己测试它:
在实现ApplicationRunner
或CommandLineRunner
时,使用参数--my config=xyz
运行应用程序将提供以下结果:
@Component
public class CLIRunner implements CommandLineRunner {
@Override
public void run(String...args) throws Exception {
System.out.println("Arguments passed when bootstraping the app: " + Arrays.asList(args));
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Arguments passed when bootstraping the app: " + args.getOptionNames());
}
}
使用CommandLineRunner
:
@Component
public class CLIRunner implements CommandLineRunner {
@Override
public void run(String...args) throws Exception {
System.out.println("Arguments passed when bootstraping the app: " + Arrays.asList(args));
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Arguments passed when bootstraping the app: " + args.getOptionNames());
}
}
输出:
Arguments passed when bootstraping the app: [--my-config=xyz]
Arguments passed when bootstraping the app: [my-config]
使用ApplicationRunner
:
@Component
public class CLIRunner implements CommandLineRunner {
@Override
public void run(String...args) throws Exception {
System.out.println("Arguments passed when bootstraping the app: " + Arrays.asList(args));
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("Arguments passed when bootstraping the app: " + args.getOptionNames());
}
}
输出:
Arguments passed when bootstraping the app: [--my-config=xyz]
Arguments passed when bootstraping the app: [my-config]
正如您所看到的,它们提供了几乎相同的功能。我建议始终使用
ApplicationRunner
,因为这样您就不必自己解析参数了,因为Spring已经解析了参数,并且在ApplicationArguments
对象中为您提供了参数。CommandLineRunner和ApplicationRunner之间的区别在于run()CommandLineRunner的方法接受字符串数组作为参数,ApplicationRunner的run()方法接受spring ApplicationArguments作为参数
要按顺序执行它们,可以使用spring@order注释或Ordered接口。这是通过查看spring代码获得的问题的真实答案。所有运行程序在启动结束时都由主线程通过以下方法运行:
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);
}
}
}
private void callrunner(ApplicationContext上下文、ApplicationArguments参数){
List runner=new ArrayList();
addAll(context.getBeansOfType(ApplicationRunner.class.values());
addAll(context.getBeansOfType(CommandLineRunner.class.values());
AnnotationAwareOrderComparator.sort(运行程序);
for(对象运行程序:新LinkedHashSet(运行程序)){
if(应用程序运行程序的运行程序实例){
callRunner((ApplicationRunner)runner,args);
}
if(CommandLineRunner的运行程序实例){
callRunner((CommandLineRunner)runner,args);
}
}
}
在我看来,您所做的是在同一个对象上实现两个runner接口。执行此操作时,上面的代码显示首先运行ApplicationRunner
方法,然后运行CommandLineRunner
方法。但你似乎说你看到了相反的行为。我实现了一个类,该类实现了两个运行程序,并且我看到这两个方法按照我期望的顺序执行
因此,您必须在两个不同的类中实现这些接口。在这种情况下,顺序由annotationawaroredercomparator.sort
方法选择对两个运行程序类排序的方式决定,因为根据上述代码,此方法用于对所有运行程序列表进行排序,以确定调用它们的顺序
注释AwareOrderComparator的说明如下:
AnnotationAwareOrderComparator是OrderComparator的扩展,支持Spring的有序接口以及@Order和@Priority注释,有序实例提供的顺序值覆盖静态定义的注释值(如果有)
排序方法的描述如下:
使用默认的AnnotationAwareOrderComparator对给定列表进行排序
显然,如果您想强制运行程序执行特定的顺序,可以使用@order或@Priority注释来完成
好了。如果您需要更多的详细信息,您需要深入了解AnnotationAwareOrderComparator
如何选择对两个类进行排序的详细信息。您希望看到什么行为?一个怎么能不跑在另一个之前呢?奇怪的是,我只是想知道这种行为