zoukankan      html  css  js  c++  java
  • 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 排最后。


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

  • 相关阅读:
    行列转换等经典SQL语句
    [jQuery]使用jQuery.Validate进行客户端验证(中级篇上)——不使用微软验证控件的理由
    深入分析jQuery.prototype.init选择器源码
    浅析jQuery基础框架
    GCC入门 ——-转载
    [转载]在VC中使用 Flash 美化你的程序
    用VS调试 javascript
    如何提高程序性能
    线程安全的懒单例模版类
    各种计算机语言的经典书籍 (转载)
  • 原文地址:https://www.cnblogs.com/binarylei/p/10426083.html
Copyright © 2011-2022 走看看