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

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 排最后。


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

猜你喜欢

转载自www.cnblogs.com/binarylei/p/10426083.html
今日推荐