记录一个springcloud-task-core.jar导致CommandLineRunner @order排序失效的问题
项目中编写了几个CommandLineRunner,并且加上了spring的@order注解,期望在启动时会按顺序执行(从order的value小到大执行),但是实际使用发现排序不生效
于是进行debug,CommandLineRunner类的排序是在 SpringApplication.class的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 applicationRunner) {
callRunner(applicationRunner, args);
}
if (runner instanceof CommandLineRunner commandLineRunner) {
callRunner(commandLineRunner, args);
}
}
}
而实际排序逻辑放在**AnnotationAwareOrderComparator **的父类 OrderComparator,就是按照@order的value从小到大排序,debug发现拿不到order注解的value,尝试实现PriorityOrdered接口但debug发现instanceof 却判断自定义的CommandLineRunner没实现PriorityOrdered接口
@Override
public int compare(@Nullable Object o1, @Nullable Object o2) {
return doCompare(o1, o2, null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
//实现了PriorityOrdered接口发现这里还是false
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
//debug发现这里拿到的是默认value
int i1 = getOrder(o1, sourceProvider);
int i2 = getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
经过debug发现项目中扫描出来的runner不是自定义CommandLineRunner 原本的类型
正常来说应该是像下图demo这样,能获取到CommandLineRunner 原本的类
那么肯定是这些bean被什么地方修改过了,顺着这个被修改成的类:ObservationCommandLineRunner,我们找到了这个罪魁祸首
class ObservationCommandLineRunnerBeanPostProcessor implements BeanPostProcessor {
private final BeanFactory beanFactory;
ObservationCommandLineRunnerBeanPostProcessor(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof CommandLineRunner commandLineRunner && !(bean instanceof ObservationCommandLineRunner)) {
return new ObservationCommandLineRunner(this.beanFactory, commandLineRunner, beanName);
}
return bean;
}
}
发现该** ObservationCommandLineRunnerBeanPostProcessor **会把所有CommandLineRunner 转换为ObservationCommandLineRunner,导致排序的order值获取不到,而这个类是pom中引入的springcloud-task-core.jar v3.0.3 引入的,因此想要达到排序效果只能暂时通过beanname的字典顺序,如下图: