Spring 如何保证后置处理器的执行顺序

Spring 如何保证后置处理器的执行顺序 - OrderComparator

Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html)

一、JDK 自带的比较器 Comparator

1.1 Comparable

Integer 内部实现了 Comparable 接口

public final class Integer extends Number implements Comparable<Integer> {
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }
}

这样就可以用集合或数组工具进行排序,不需要再定义比较器了。

@Test
public void test() {
    // 1. 集合排序
    List<Integer> integerList = Arrays.asList(3, 2, 1, 5, 6);
    // integerList.sort()
    Collections.sort(integerList);
    Assert.assertEquals(Arrays.asList(1, 2, 3, 5, 6), integerList);

    // 2. 数组排序
    Arrays.sort(new Integer[]{3, 2, 1, 5, 6});
}

1.2 Comparator

还在另外一种情况,需要排序的对象没有实现 Comparable,那怎么办呢?JDK 提供了一个专门的比较器 Comparator。

@FunctionalInterface
public interface Comparator<T> {
	// o1>o2: 1; o1=o2: 0;o1<o2: -1;
	// Assert.assertEquals(-1, Integer.compare(1, 2));
	int compare(T o1, T o2);
}

Collections 集合对应的排序方式如下:

public static <T> void sort(List<T> list, Comparator<? super T> c) {
    list.sort(c);
}

二、Spring 中的比较器 OrderComparator

在 Spring 中提供了接口和注解两种方式,注意 Spring 中数值越小级别越高,位于 core 包中:

  • 一是实现 Ordered 或 PriorityOrdered 接口,PriorityOrdered 的级别要优先于 Ordered,使用 OrderComparator 比较器。

  • 二是使用 @Order(Spring 规范) 或 @Priority(JDK 规范) 注解,使用 AnnotationAwareOrderComparator 比较器。

2.1 OrderComparator

2.1.1 Ordered 接口

public interface PriorityOrdered extends Ordered {
}
public interface Ordered {
	int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
	int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

	int getOrder();
}

2.1.2 OrderComparator

// 实现 JDK 的 Comparator
public class OrderComparator implements Comparator<Object> {
	@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) {
		boolean p1 = (o1 instanceof PriorityOrdered);
		boolean p2 = (o2 instanceof PriorityOrdered);
		// 1. PriorityOrdered 接口优先
		if (p1 && !p2) {
			return -1;
		} else if (p2 && !p1) {
			return 1;
		}

		// 2. 比较 getOrder 的值,数值越小越优先
		int i1 = getOrder(o1, sourceProvider);
		int i2 = getOrder(o2, sourceProvider);
		return Integer.compare(i1, i2);
	}
}

使用和 JDK 一致。

2.2 AnnotationAwareOrderComparator

AnnotationAwareOrderComparator 继承自 OrderComparator 增加了 @Order(Spring 规范) 或 @Priority(JDK 规范) 注解的处理。

2.2.1 @Order

public @interface Order {
	int value() default Ordered.LOWEST_PRECEDENCE;
}

// javax.annotation.Priority
public @interface Priority {
    int value();
}

2.2.2 AnnotationAwareOrderComparator

AnnotationAwareOrderComparator 重写了 findOrder,增加了对 @Order 或 @Priority 两个注解的处理。使用 OrderUtils 工具类。

@Override
protected Integer findOrder(Object obj) {
	// Check for regular Ordered interface
	Integer order = super.findOrder(obj);
	if (order != null) {
		return order;
	}

	// Check for @Order and @Priority on various kinds of elements
	if (obj instanceof Class) {
		return OrderUtils.getOrder((Class<?>) obj);
	} else if (obj instanceof Method) {
		Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class);
		if (ann != null) {
			return ann.value();
		}
	} else if (obj instanceof AnnotatedElement) {
		Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class);
		if (ann != null) {
			return ann.value();
		}
	} else {
		order = OrderUtils.getOrder(obj.getClass());
		if (order == null && obj instanceof DecoratingProxy) {
			order = OrderUtils.getOrder(((DecoratingProxy) obj).getDecoratedClass());
		}
	}
	return order;
}

2.3 测试

有以下 4 个类,分别是实现 PriorityOrdered 接口、实现 Ordered 接口、@Order 注解、普通 bean.

class A implements PriorityOrdered {
    @Override
    public int getOrder() {
        return Ordered.LOWEST_PRECEDENCE;
    }
}
class B implements Ordered {
    @Override
    public int getOrder() {
        return 10;
    }
}
@Order(0)
class C {
}
class D {
}

测试排序的结果:

@Test
public void test() {
    List<Object> list = Arrays.asList(new D(), new C(), new B(), new A());
    AnnotationAwareOrderComparator.sort(list);
    // A C B D
    list.forEach(o -> System.out.print(o.getClass().getSimpleName() + " "));
}

A 实现了 PriorityOrdered 接口排第一位、B 和 C 分别比较 order 值、D 排最后。


每天用心记录一点点。内容也许不重要,但习惯很重要!

原文地址:https://www.cnblogs.com/binarylei/p/10426083.html