【记录版】SpringBoot框架中排序设计源码解读
SpringBoot + AnnotationAwareOrderComparator
背景: 在日常框架开发过程中,指定类执行顺序是常见操作,往往在定义Bean的时候就指定其前后顺序,以保证逻辑的正确解析与传递。通过我们直接通过添加@Order注解或者实现Ordered接口来完成,那么底层解析的逻辑是什么样的?本篇仅做简单记录。
Servlet系列精选:
1、Servlet请求体重复读&修改新姿势
2、根据请求获取后端接口详情
3、Filter链式执行设计解读
4、SpringBoot下Filter注册流程
5、SpringBoot下Filter自动适配
一、排序解析核心类
1)org.springframework.core.annotation.AnnotationAwareOrderComparator
2)org.springframework.core.annotation.OrderUtils
二、AnnotationAwareOrderComparator + OrderComparator部分代码【合并版】
public class AnnotationAwareOrderComparator extends OrderComparator {
// 通常以此方法开始解析类中的优先级属性
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
// 开始查找类定义中的@Order注解或Order接口属性
Integer order = this.findOrder(obj);
if (order != null) {
return order;
}
}
// 如果未找到相关属性,则默认最低优先级(Integer.MAX_VALUE)
return 2147483647;
}
@Nullable
protected Integer findOrder(Object obj) {
// 类实现Ordered接口,直接通过getOrder方法返回指定值
Integer order = obj instanceof Ordered ? ((Ordered)obj).getOrder() : null;
// 获取其他场景优先级属性【复杂版】
return order != null ? order : this.findOrderFromAnnotation(obj);
}
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
// AnnotatedElement是jdk1.5引入的反射核心类,Clas、Method、Field、Parameter都是其子类
AnnotatedElement element = obj instanceof AnnotatedElement ? (AnnotatedElement)obj : obj.getClass();
// 此处指定注解解析策略,层级搜索,包含父类及父接口的所有注解
MergedAnnotations annotations = MergedAnnotations.from((AnnotatedElement)element, SearchStrategy.TYPE_HIERARCHY);
// 通过OrderUtils工具类获取注解集合中的@Order或@Priority
Integer order = OrderUtils.getOrderFromAnnotations((AnnotatedElement)element, annotations);
// 如果Bean定义负责,涉及其他框架AOP代理封装,此处将原始Bean定义拿出解析
// 在此之前没有判断是否代理,其他框架在AOP实现时可以添加优先级属性以实现辅助功能执行顺序调整?+
// 注意:这块出现了递归调用
return order == null && obj instanceof DecoratingProxy ? this.findOrderFromAnnotation(((DecoratingProxy)obj).getDecoratedClass()) : order;
}
@Nullable
// Priority注解处理
public Integer getPriority(Object obj) {
if (obj instanceof Class) {
return OrderUtils.getPriority((Class)obj);
} else {
Integer priority = OrderUtils.getPriority(obj.getClass());
return priority == null && obj instanceof DecoratingProxy ? this.getPriority(((DecoratingProxy)obj).getDecoratedClass()) : priority;
}
}
}
三、OrderUtils类代码
// 工具类,皆静态方法,abstract修饰类避免创建实例
public abstract class OrderUtils {
private static final Object NOT_ANNOTATED = new Object();
private static final String JAVAX_PRIORITY_ANNOTATION = "javax.annotation.Priority";
// 解析结果缓存,以空间换时间
// MergedAnnotations搜索优先级属性更耗时为啥没缓存?搜索策略多样的原因吗
private static final Map<AnnotatedElement, Object> orderCache = new ConcurrentReferenceHashMap(64);
public OrderUtils() {
}
public static int getOrder(Class<?> type, int defaultOrder) {
Integer order = getOrder(type);
return order != null ? order : defaultOrder;
}
@Nullable
public static Integer getOrder(Class<?> type, @Nullable Integer defaultOrder) {
Integer order = getOrder(type);
return order != null ? order : defaultOrder;
}
@Nullable
public static Integer getOrder(Class<?> type) {
return getOrder((AnnotatedElement)type);
}
@Nullable
public static Integer getOrder(AnnotatedElement element) {
return getOrderFromAnnotations(element, MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY));
}
@Nullable
// AnnotationAwareOrderComparator中调用的工具方法
static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) {
if (!(element instanceof Class)) {
return findOrder(annotations);
} else {
Object cached = orderCache.get(element);
if (cached != null) {
return cached instanceof Integer ? (Integer)cached : null;
} else {
Integer result = findOrder(annotations);
orderCache.put(element, result != null ? result : NOT_ANNOTATED);
return result;
}
}
}
@Nullable
private static Integer findOrder(MergedAnnotations annotations) {
// Order注解解析
MergedAnnotation<Order> orderAnnotation = annotations.get(Order.class);
if (orderAnnotation.isPresent()) {
return orderAnnotation.getInt("value");
} else {
// Priority注解解析
MergedAnnotation<?> priorityAnnotation = annotations.get("javax.annotation.Priority");
return priorityAnnotation.isPresent() ? priorityAnnotation.getInt("value") : null;
}
}
@Nullable
public static Integer getPriority(Class<?> type) {
return (Integer)MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY).get("javax.annotation.Priority").getValue("value", Integer.class).orElse((Object)null);
}
优先级属性获取流程都清楚了,日常怎么使用?
public int AnnotationAwareOrderComparator.compare(@Nullable Object o1, @Nullable Object o2)
【Collection<E>】.stream()
.sorted(AnnotationAwareOrderComparator.INSTANCE)
.collect(Collectors.toList())
如果自己想获取优先级属性的具体解析值,如Filter适配逻辑中的需求,那怎么办?直接调用getOrder方法吗?其实不是…
public int getOrder(Object value) {
return (new AnnotationAwareOrderComparator() {
public int getOrder(Object obj) {
return super.getOrder(obj);
}
}).getOrder(value);
}
为什么这样麻烦?还不是protected惹的祸,设计者就没想对外开放,一般人也没这个需求,工具类都是直接走compare方法了。
总结:
1、优先级围绕Order注解、Ordered接口、@Priority注解展开,优先使用前两个
2、注解从jdk1.5开始,AnnotatedElement父接口提供了反射时注解相关的解析方法,后期给我们自定义注解及AOP使用带了极大的便利性
3、优先级属性只作为参考,只有后台有排序逻辑才有意义,一般只有同类对象才会处理,如Spring各自bean间的执行顺序不依赖此属性
4、如果依赖第三方包,且需要对同类排序,但是依赖实例都没有定义优先级属性,此时默认都是最低优先级,执行顺序就按BeanDefinition的扫描顺序了,这个扫描顺序每个项目还不固定,这时候就考验自己的能力了,各种奇形怪状的问题就会出现了。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!