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 后置处理器
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- centos 升级sqlite3
1.yum remove sqlite3 2. 下载: wget -O sqlite-autoconf-.tar.gz https://www.sqlite.org/2019/sqlite-autoc ...
- 如何添加Modeling 菜单
创建page 在protal settings的cdoform中add new item 在modeing中就可以使用该对象对应的维护页面了.
- jQuery 设置/获取样式
参考 http://www.w3school.com.cn/jquery/jquery_css.asp $("#a").css("height"); $(&qu ...
- Centos 7 下 Corosync + Pacemaker + psc + HA-proxy 实现业务高可用
一.介绍: 1.本博客Corosync + Pacemaker + psc + HA-proxy 实现业务高可用,以httpd 服务实现高可用为例. 2.架构思路 a.三台web 节点,功能:全部安装 ...
- Devexpress Gridview 自定义汇总CustomSummaryCalculate(加权平均)
Devexpress Gridview 提供了简单的求和,平均等方法,复杂的汇总方法则需要自定义,使用gridview 的CustomSummaryCalculate 事件,根据官网的文档及各论坛案例 ...
- javascript简单的滑动效果
利用setInterval实现简单的滑动效果 <!DOCTYPE html> <html lang="en"> <head> <meta ...
- 微信小程序开发-rem转换rpx小工具
实现原理: 对样式进行格式化,然后根据 “rem” 进行拆分,这样就会拆分成一个数组 [str1,str2,str3...,str6], 除了最后一个元素,前边的元素都会以 “rem” 样式的数值结尾 ...
- Linq 查询 List集合
总是听到身边的同事说起Linq ,知道上学的时候学过,可是自从毕业之后就再也没用过,总觉得是很牛的技能 ,可是当自己真正学会用的时候才发现,我去,So easy .废话不多说直接上代码吧 var li ...
- 实现Hibernate框架的CRUD
1.创建Web项目HS_test如图所示: 2.创建数据库DBHSTest,在数据库中创建表Teacher,并插入数据 3.在Myeclipse中调出DB Brower视图 右键->New: 连 ...
- Java09-java语法基础(八)java中的方法
Java09-java语法基础(八)java中的方法 一.方法(函数/过程):是一个程序块,可以完成某种功能 1.java中方法的定义格式 [访问控制修饰符] 返回值类型 方法名(参数列表){ 方 ...