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 排最后。
每天用心记录一点点。内容也许不重要,但习惯很重要!
Spring 如何保证后置处理器的执行顺序 - OrderComparator的更多相关文章
- Spring之BeanPostProcessor(后置处理器)介绍
为了弄清楚Spring框架,我们需要分别弄清楚相关核心接口的作用,本文来介绍下BeanPostProcessor接口 BeanPostProcessor 该接口我们也叫后置处理器,作用是在Be ...
- Spring点滴五:Spring中的后置处理器BeanPostProcessor讲解
BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...
- spring学习四:Spring中的后置处理器BeanPostProcessor
BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...
- Spring的BeanPostProcessor后置处理器与bean的生命周期
前言 本文将把Spring在Bean的生命周期中涉及到的后置处理器一一梳理出来,并简要说一下功能,至于每个后置处理器在实际扩展中的用处,还要后续慢慢探索总结. 正文 下面一步步跟进探寻那些后置处理器们 ...
- spring中Bean后置处理器实现总结
BeanPostProcessor接口 bean的后置处理器实现功能主要是 可以在bean初始化之前和之后做增强处理.自定义MyBeanProcessor实现BeanPostProcessor接口,重 ...
- Spring Bean前置后置处理器的使用
Spirng中BeanPostProcessor和InstantiationAwareBeanPostProcessorAdapter两个接口都可以实现对bean前置后置处理的效果,那这次先讲解一下B ...
- Spring中的后置处理器BeanPostProcessor讲解
Spring中提供了很多PostProcessor供开发者进行拓展,例如:BeanPostProcessor.BeanFactoryPostProcessor.BeanValidationPostPr ...
- 2.3 spring5源码系列---内置的后置处理器PostProcess加载源码
本文涉及主题 1. BeanFactoryPostProcessor调用过程源码剖析 2. 配置类的解析过程源码 3. 配置类@Configuration加与不加的区别 4. 重复beanName的覆 ...
- [原创]java WEB学习笔记101:Spring学习---Spring Bean配置:IOC容器中bean的声明周期,Bean 后置处理器
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- pandas 常用清洗数据(三)排序,去重
1.排序 DataFrame 按照Index排序 Series.order()进行排序,而DataFrame则用sort或者sort_index或者sort_values 2.去重, dt = dt. ...
- js中基本事件的总结,onclick、onblur、onchange等
js中的基本事件总结: 特定的场景下发生的一个动作:事件:事件=函数(),事件发生会触发函数执行. 属性 当以下情况发生时,出现此事件 FF N IE onabort 图像加载被中断 1 3 4 on ...
- 预览InputFile
[预览InputFile] 通过input的files属性,可以取到选择的File对象,通过FileReader可以将File对象读取出来. <body> <input type=& ...
- Linux系统服务之inetd
[Linux系统服务之inetd] inetd的角色是作为Telnet和FTP等与网络服务器相关的进程的“超级服务器”.这是一个简单的道理:并不是全部的服务器进程(包括那些接受新的Telnet和FTP ...
- 外购半成品报SHORT问题(验货客户)
描述:下图中可以看到外购半成品层物料报SHORT 2.开始检查数据 --针对外购半成品(外购半成品的成品层有BOM数据,外购半成品没有BOM数据) '; --select * from TB_ADDB ...
- Java Runtime
Runtime 类代表着Java程序的运行时环境,构造方法 private Runtime(){},采用单例模式,一个jvm只有一个Runtime实例对象,该类会被自动创建,我们可以通过Runtime ...
- Access sql语句创建表及字段类型(转)
http://www.cnblogs.com/hnyei/archive/2012/02/23/2364812.html 创建一张空表: Sql="Create TABLE [表名]&quo ...
- 微信小程序开发——模板中加载html代码
最新方法可以使用微信小程序提供的 rich-text (富文本)组件直接写解析html,详见 rich-text: <rich-text class='f13 c_9' nodes=" ...
- PTA 7-50 畅通工程之局部最小花费问题(最小生成树Kruskal)
某地区经过对城镇交通状况的调查,得到现有城镇间快速道路的统计数据,并提出“畅通工程”的目标:使整个地区任何两个城镇间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可). ...
- [剑指Offer]12-矩阵中的路径(回溯)
题目链接 https://www.nowcoder.com/practice/c61c6999eecb4b8f88a98f66b273a3cc?tpId=13&tqId=11218&t ...