Order注解
@Order
注解定义了类、方法和字段的优先级(排序情况),value
是可选的,默认为Ordered.LOWEST_PRECEDENCE,即最低优先级。表示 Ordered
接口中的 order 属性。
目前看到的 @Order 注解都是用在类上的,没有看到过用在方法和字段上的,包括 Spring 自有类 DefaultErrorAttributes、LogbackLoggingSystem.Factory 等。
1 2 3 4 5 6 7 8 9 10 11 12 13
| @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @Documented public @interface Order {
int value() default Ordered.LOWEST_PRECEDENCE;
}
|
从 Spring 4.0 开始,Spring 中的很多组件都支持基于 Order
注解的排序,使用了该注解后,会影响依赖注入的优先级,但是不影响bean的加载顺序,因为加载顺序受依赖关系和 @DependsOn
声明影响的。
这句理解上还是有问题~
从 Spring 4.1 开始,jakarta.annotation.Priority
可在一些排序场景中替代 @Order
的作用,但是在修饰单个元素时,@Priority
可能具有其他语义。
除了这两个注解外,也可以实现 Ordered
接口,来设置优先级信息,相对使用注解的方式更加灵活。
Priority注解
@Priority
注解位于 jakarta.annotation
包下,可以标识类或参数以什么样的顺序来执行或使用。
Priority
注解的具体作用由具体的使用类来定义,如在Jakarta Interceptors 规范定义了使用拦截器的优先级来控制调用拦截器的顺序。
value
一般情况下应该是非负值,负值作为保留值有特定的含义,如“未定义”或“未指定”等。
定义 @Priority
使用的规范可以定义允许的优先级范围和任何具有特殊含义的优先级值。
1 2 3 4 5 6 7 8 9
| @Target({TYPE,PARAMETER}) @Retention(RUNTIME) @Documented public @interface Priority {
int value(); }
|
@Priority
的 value
越小,优先级越高。
OrderUtils类
OrderUtils
用于对添加了 @Order
注解和 @Priority
注解的类,根据声明的顺序和优先级进行处理,相当于是两个注解的具体实现。
OrderUtils
提供了三个常量:
1 2 3 4 5 6 7 8
| private static final Map<AnnotatedElement, Object> orderCache = new ConcurrentReferenceHashMap<>(64);
private static final Object NOT_ANNOTATED = new Object();
private static final String JAVAX_PRIORITY_ANNOTATION = "jakarta.annotation.Priority";
|
针对 @Order
和 @Priority
注解提供了4个 getOrder
的方法,进行排序值的获取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| 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)); }
|
可以看到,getOrder(Class<?> type, int defaultOrder)
和 getOrder(Class<?> type, @Nullable Integer defaultOrder)
调用了 getOrder(Class<?> type)
, 而 getOrder(Class<?> type)
则调用了 getOrder(AnnotatedElement element)
。
看看 getOrderFromAnnotations
的具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
@Nullable static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) { if (!(element instanceof Class)) { return findOrder(annotations); } Object cached = orderCache.get(element); if (cached != null) { return (cached instanceof Integer ? (Integer) cached : null); } Integer result = findOrder(annotations); orderCache.put(element, result != null ? result : NOT_ANNOTATED); return result; }
@Nullable private static Integer findOrder(MergedAnnotations annotations) { MergedAnnotation<Order> orderAnnotation = annotations.get(Order.class); if (orderAnnotation.isPresent()) { return orderAnnotation.getInt(MergedAnnotation.VALUE); } MergedAnnotation<?> priorityAnnotation = annotations.get(JAVAX_PRIORITY_ANNOTATION); if (priorityAnnotation.isPresent()) { return priorityAnnotation.getInt(MergedAnnotation.VALUE); } return null; }
|
最后针对 @Priority
注解单独提供了 getPriority(Class<?> type)
方法,获取优先级的数值,如果没有添加注解或者 value
未设值,则返回 null。
1 2 3 4 5
| @Nullable public static Integer getPriority(Class<?> type) { return MergedAnnotations.from(type, SearchStrategy.TYPE_HIERARCHY).get(JAVAX_PRIORITY_ANNOTATION) .getValue(MergedAnnotation.VALUE, Integer.class).orElse(null); }
|
Ordered接口
优先级排序接口,和 @Order
注解一样,获取到的 order 值越小,优先级越高。
1 2 3 4 5
| int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
|
提供获取排序值的方法,如果两个对象的 order 值相同,则会进行随机排序。
PriorityOrdered接口
Ordered
接口的扩展接口,表示优先级排序。
PriorityOrdered
接口的优先级要高于 Ordered
接口的优先级,即使后者对应的 order 值比较小,也是 PriorityOrdered
的优先级高。
在对一组对象进行排序时, PriorityOrdered
对象和 Ordered
对象可以被看作两个单独的子集,其中一组 PriorityOrdered
对象位于一组 Ordered
对象之前,然后在这两个子集中再根据 order 进行相对排序。
PriorityOrdered
是一个专用接口,用于标记特别重要的的对象,甚至不需要获取剩余的对象,比如 Spring 中优先级比较高的后置处理器 ApplicationContext
。PriorityOrdered
相关的后置处理器 Bean 在特殊阶段进行初始化,早于其他的后置处理器,这巧妙地影响了它们的自动装配行为:只会针对不需要急切初始化类型匹配的 bean 进行自动装配。
PriorityOrdered
的应用可参见 org.springframework.beans.factory.config.PropertyOverrideConfigurer
类。