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 后置处理器
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
随机推荐
- Promise.then
[Promise.then] 1.If onFulfilled returns a promise, the return value of then will be resolved/rejecte ...
- 第七篇:Jmeter连接MySQL的测试
.准备一个有数据表格的MySQL数据库: 2.在测试计划面板上点击浏览按钮,把你的JDBC驱动添加进来: mysql-connector-java-5.1.26-bin.jar 3.添加一个线程组-- ...
- angularjs directive scope 与父scope双向绑定
参考 http://www.jb51.net/article/83051.htm angluar.module("aaa").directive("testDirecti ...
- 一些网站的meta标签的作用
转载:https://www.cnblogs.com/Lily-nercel/p/6693293.html <!DOCTYPE html> <html lang="en&q ...
- 15. 3Sum (重新分配数组大小)
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...
- Intent Activity跳转 传递数据 Bundle
1.普通跳转: Intent intent=new Intent(); intent.setClass(MainActivity.this,NewActivity.class); //新建一个Inte ...
- 一字一句的搞懂vue-cli之vue webpack template配置
webpack--神一样的存在.无论写了多少次,再次相见,仍是初见.有的时候开发vue项目,对尤大的vue-cli感激涕零.但是,但是,但是...不是自己的东西,真的很不想折腾.所以,我们就得深入内部 ...
- linux命令学习之:ps
Linux中的ps命令是Process Status的缩写.ps命令用于报告当前系统的进程状态,列出系统中当前运行的那些进程.可以搭配kill指令随时中断.删除不必要的程序. 要对进程进行监测和控制, ...
- linux命令学习之:curl
curl命令是一个利用URL规则在命令行下工作的开源文件传输工具.它支持文件的上传和下载,所以是综合传输工具,但按传统,习惯称curl为下载工具.作为一款强力工具,curl支持包括HTTP.HTTPS ...
- 如何查看Firefox中保存的登录密码
问:以前使用Firefox浏览器登录一个论坛,并且临时申请了一个账号,在使用Firefox登录时选择让它记住密码了,后来,我忘记了那个论坛的密码,但是可以使用Firefox直接登录.现在能不能查看密码 ...