记录一个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的字典顺序,如下图:

posted @ 2024-04-11 11:18  CodeSpike  阅读(23)  评论(0编辑  收藏  举报
Live2D