Spring 如何保證後置處理器的執行順序 - OrderComparator

Spring 如何保證後置處理器的執行順序 - OrderComparator

Spring 系列目錄(http://www.javashuo.com/article/p-kqecupyl-bm.html)html

1、JDK 自帶的比較器 Comparator

1.1 Comparable

Integer 內部實現了 Comparable 接口java

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);
    }
}

這樣就能夠用集合或數組工具進行排序,不須要再定義比較器了。spring

@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 集合對應的排序方式以下:ide

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

2、Spring 中的比較器 OrderComparator

在 Spring 中提供了接口和註解兩種方式,注意 Spring 中數值越小級別越高,位於 core 包中:工具

  • 一是實現 Ordered 或 PriorityOrdered 接口,PriorityOrdered 的級別要優先於 Ordered,使用 OrderComparator 比較器。測試

  • 二是使用 @Order(Spring 規範) 或 @Priority(JDK 規範) 註解,使用 AnnotationAwareOrderComparator 比較器。this

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 一致。code

2.2 AnnotationAwareOrderComparator

AnnotationAwareOrderComparator 繼承自 OrderComparator 增長了 @Order(Spring 規範) 或 @Priority(JDK 規範) 註解的處理。htm

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


天天用心記錄一點點。內容也許不重要,但習慣很重要!

相關文章
相關標籤/搜索