Spring核心接口之Ordered

一、Ordered接口介绍
Spring中提供了一个Ordered接口。从单词意思就知道Ordered接口的作用就是用来排序的。
Spring框架是一个大量使用策略设计模式的框架,这意味着有很多相同接口的实现类,那么必定会有优先级的问题。于是Spring就提供了Ordered这个接口,来处理相同接口实现类的优先级问题。

二、Ordered接口分析
1、Ordered接口的定义:

 public interface Ordered {
/*** Useful constant for the highest precedence value.
 * @see java.lang.Integer#MIN_VALUE
 */
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;

/**
 * Useful constant for the lowest precedence value.
 * @see java.lang.Integer#MAX_VALUE
 */
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

/**
 * Get the order value of this object.
 * <p>Higher values are interpreted as lower priority. As a consequence,
 * the object with the lowest value has the highest priority (somewhat
 * analogous to Servlet {@code load-on-startup} values).
 * <p>Same order values will result in arbitrary sort positions for the
 * affected objects.
 * @return the order value
 * @see #HIGHEST_PRECEDENCE
 * @see #LOWEST_PRECEDENCE
 */
int getOrder();

}

该接口卡只有1个方法getOrder()及 2个变量HIGHEST_PRECEDENCE最高级(数值最小)和LOWEST_PRECEDENCE最低级(数值最大)。

2、OrderComparator类:实现了Comparator接口的一个比较器。

public class OrderComparator implements Comparator<Object> {
/**
 * Shared default instance of OrderComparator.
 */
public static final OrderComparator INSTANCE = new OrderComparator();

public int compare(Object o1, Object o2) {
    boolean p1 = (o1 instanceof PriorityOrdered);
    boolean p2 = (o2 instanceof PriorityOrdered);
    if (p1 && !p2) {
        return -1;
    }
    else if (p2 && !p1) {
        return 1;
    }

    // Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
    int i1 = getOrder(o1);
    int i2 = getOrder(o2);
    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}

/**
 * Determine the order value for the given object.
 * <p>The default implementation checks against the {@link Ordered}
 * interface. Can be overridden in subclasses.
 * @param obj the object to check
 * @return the order value, or {@code Ordered.LOWEST_PRECEDENCE} as fallback
 */
protected int getOrder(Object obj) {
    return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : Ordered.LOWEST_PRECEDENCE);
}

/**
 * Sort the given List with a default OrderComparator.
 * <p>Optimized to skip sorting for lists with size 0 or 1,
 * in order to avoid unnecessary array extraction.
 * @param list the List to sort
 * @see java.util.Collections#sort(java.util.List, java.util.Comparator)
 */
public static void sort(List<?> list) {
    if (list.size() > 1) {
        Collections.sort(list, INSTANCE);
    }
}

/**
 * Sort the given array with a default OrderComparator.
 * <p>Optimized to skip sorting for lists with size 0 or 1,
 * in order to avoid unnecessary array extraction.
 * @param array the array to sort
 * @see java.util.Arrays#sort(Object[], java.util.Comparator)
 */
public static void sort(Object[] array) {
    if (array.length > 1) {
        Arrays.sort(array, INSTANCE);
    }
}
}

提供了2个静态排序方法:sort(List<?> list)用来排序list集合、sort(Object[] array)用来排序Object数组
可以下OrderComparator类的public int compare(Object o1, Object o2)方法,可以看到另外一个类PriorityOrdered,这个方法的逻辑解析如下:

  1. 若对象o1是Ordered接口类型,o2是PriorityOrdered接口类型,那么o2的优先级高于o1
  2. 若对象o1是PriorityOrdered接口类型,o2是Ordered接口类型,那么o1的优先级高于o2
  3. 其他情况,若两者都是Ordered接口类型或两者都是PriorityOrdered接口类型,调用Ordered接口的getOrder方法得到order值,order值越大,优先级越小
    简单来说就是:
    OrderComparator比较器进行排序的时候,若2个对象中有一个对象实现了PriorityOrdered接口,那么这个对象的优先级更高。若2个对象都是PriorityOrdered或Ordered接口的实现类,那么比较Ordered接口的getOrder方法得到order值,值越低,优先级越高。

三、Spring中使用Ordered接口在的例子
在spring配置文件中添加:<mvc:annotation-driven/>,那么SpringMVC默认会注入RequestMappingHandlerAdapter和RequestMappingHandlerMapping这两个类。 既然SpringMVC已经默认为我们注入了RequestMappingHandlerAdapter和RequestMappingHandlerMapping这两个类,如果再次配置这两个类,将会出现什么效果呢?
当我们配置了annotation-driven以及这两个bean的时候。Spring容器就有了2个RequestMappingHandlerAdapter和2个RequestMappingHandlerMapping。
DispatcherServlet内部有HandlerMapping(RequestMappingHandlerMapping是其实现类)集合和HandlerAdapter(RequestMappingHandlerAdapter是其实现类)集合。
//RequestMappingHandlerMapping集合
private List<HandlerMapping> handlerMappings;
//HandlerAdapter集合
private List<HandlerAdapter> handlerAdapters;
在仔细看下DispatcherServlet类的private void initHandlerMappings(ApplicationContext context)方法可以看到如下代码:
//detectAllHandlerMappings默认为true
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map<String, HandlerMapping> matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
// We keep HandlerMappings in sorted order.
//进行排序
AnnotationAwareOrderComparator.sort(this.handlerMappings);
}
}
AnnotationAwareOrderComparator继承了OrderComparator类

再看下<mvc:annotation-driven/>配置的RequestMappingHandlerMapping和RequestMappingHandlerAdapter@Bean
br/>@Bean
br/>@Bean

进入RequestMappingHandlerMapping和RequestMappingHandlerAdapter代码里面看看它们的order属性是如何定义的。
RequestMappingHandlerMapping
// Ordered.LOWEST_PRECEDENCE只为Integer.MAX_VALUE
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
    implements HandlerMapping, Ordered {
    private int order = Integer.MAX_VALUE; 

AbstractHandlerMapping是RequestMappingHandlerMapping的父类。

RequestMappingHandlerAdapter
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered {
    // Ordered.LOWEST_PRECEDENCE只为Integer.MAX_VALUE
    private int order = Ordered.LOWEST_PRECEDENCE;

AbstractHandlerMethodAdapter是RequestMappingHandlerAdapter的父类。   可以看到RequestMappingHandlerMapping和RequestMappingHandlerAdapter没有设置order属性的时候,order属性的默认值都是Integer.MAX_VALUE,即优先级最低。 

总结: 如果配置了<mvc:annotation-driven/>,又配置了自定义的RequestMappingHandlerAdapter,并且没有设置RequestMappingHandlerAdapter的order值,那么这2个RequestMappingHandlerAdapter的order值都是Integer.MAX_VALUE。那么谁先定义的,谁优先级高。 <mvc:annotation-driven/>配置在自定义的RequestMappingHandlerAdapter配置之前,那么<mvc:annotation-driven/>配置的RequestMappingHandlerAdapter优先级高,反之自定义的RequestMappingHandlerAdapter优先级高。

如果配置了<mvc:annotation-driven/>,又配置了自定义的RequestMappingHandlerMapping,并且没有设置RequestMappingHandlerMapping的order值。那么<mvc:annotation-driven/>配置的RequestMappingHandlerMapping优先级高,因为<mvc:annotation-driven />内部会设置RequestMappingHandlerMapping的order为0。

四、应用
1、定义接口
import java.util.Map;
import org.springframework.core.Ordered;

public interface Filter extends Ordered{
    public void doFiler(Map<String, String> prams);

}

2、实现接口

import java.util.Map;
    @Component
    public class LogFilter implements Filter {
        private int order =1;
        public int getOrder() {
            return order;
        }
        public void setOrder(int order) {
            this.order = order;
        }
        public void doFiler(Map<String, String> prams) {
            System.out.println("打印日志");
        }
    }

import java.util.Map;
@Component
public class PowerLogFilter implements Filter {
    private int order =2;
    public int getOrder() {
        return order;
    }
    public void setOrder(int order) {
        this.order = order;
    }
    public void doFiler(Map<String, String> prams) {
        System.out.println("权限控制");
    }
}

3、测试进行排序
public static void main(String[] args) throws Exception {
String config = Test.class.getPackage().getName().replace('.', '/') + "/bean.xml";
   ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(config);
   context.start();
   Map<String, Filter> filters = context.getBeansOfType(Filter.class);
    System.out.println(filters.size());
   List<Filter> f= new ArrayList<Filter>(filters.values());
   OrderComparator.sort(f);
   for(int i=0; i<f.size(); i++){
       Map<String, String> params = new HashMap<String, String>();
       f.get(i).doFiler(params);
   }
}

4、配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<context:component-scan base-package="com" />

</beans>

Spring核心接口之Ordered

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍了spring的事务传播属性REQUIRED_NESTED的原理介绍,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。传统事务中回滚点的使...
今天小编给大家分享的是一文解析spring中事务的传播机制,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
这篇文章主要介绍了SpringCloudAlibaba和SpringCloud有什么区别,具有一定借鉴价值,需要的朋友可以参考下。下面就和我一起来看看吧。Spring Cloud Netfli...
本篇文章和大家了解一下SpringCloud整合XXL-Job的几个步骤。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。第一步:整合pom文件,在S...
本篇文章和大家了解一下Spring延迟初始化会遇到什么问题。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。List 坑列表 = new ArrayList(2);...
这篇文章主要介绍了怎么使用Spring提供的不同缓存注解实现缓存的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇...
本篇内容主要讲解“Spring中的@Autowired和@Resource注解怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学...
今天小编给大家分享一下SpringSecurity怎么定义多个过滤器链的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家
这篇文章主要介绍“Spring的@Conditional注解怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring的@Con...
这篇文章主要介绍了SpringCloudGateway的熔断限流怎么配置的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇SpringCloud&nb...
今天小编给大家分享一下怎么使用Spring解决循环依赖问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考
这篇文章主要介绍“Spring事务及传播机制的原理及应用方法是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Sp...
这篇“SpringCloudAlibaba框架实例应用分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价
本篇内容主要讲解“SpringBoot中怎么使用SpringMVC”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习...
这篇文章主要介绍“SpringMVC适配器模式作用范围是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringMVC
这篇“导入SpringCloud依赖失败如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要讲解了“SpringMVC核心DispatcherServlet处理流程是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来
今天小编给大家分享一下SpringMVCHttpMessageConverter消息转换器怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以...
这篇文章主要介绍“Spring框架实现依赖注入的原理是什么”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Spring框架...
本篇内容介绍了“Spring单元测试控制Bean注入的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下