目录

前言

Spring中提供了一个Ordered接口。Ordered接口,顾名思义,就是用来排序的。

Spring是一个大量使用策略设计模式的框架,这意味着有很多相同接口的实现类,那么必定会有优先级的问题。

于是,Spring就提供了Ordered这个接口,来处理相同接口实现类的优先级问题。

Ordered接口介绍

首先,我们来看下Ordered接口的定义:

public interface Ordered {

    int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;

    int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

    int getOrder();

}

只有1个方法:getOrder();  2个变量:最高级(数值最小)和最低级(数值最大)。

OrderComparator类:实现了Comparator的一个比较器。

提供了3个静态排序方法:sort(List<?> list)、sort(Object[] array)、sortIfNecessary(Object value)。根据OrderComparator对数组和集合进行排序。

sortIfNecessary方法内部会判断value参数是Object[]还是List类型,然后使用Object[]参数的sort方法和List参数的sort方法进行排序。

我们看下这个比较器的compare方法:

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;
} int i1 = getOrder(o1);
int i2 = getOrder(o2);
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}

PriorityOrdered是个接口,继承自Ordered接口,未定义任何方法。

这段代码的逻辑:

  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值,值越低,优先级越高。

Ordered接口在Spring中的使用

以SpringMVC为例,举例Ordered接口的运用。

<mvc:annotation-driven/>

这段配置在*-dispatcher.xml中定义的话,那么SpringMVC默认会注入RequestMappingHandlerAdapter和RequestMappingHandlerMapping这两个类。

关于这部分的内容,请参考楼主的另外一篇博客:http://www.cnblogs.com/fangjian0423/p/springMVC-xml-json-convert.html#analysis

既然SpringMVC以及默认为我们注入了RequestMappingHandlerAdapter和RequestMappingHandlerMapping这两个类,我们是否可以再次配置这两个类?

答案当然是可以的。

RequestMappingHandlerMapping:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
<property name="interceptors">
<bean class="package.interceptor.XXInterceptor"/>
</property>
<property name="order" value="-1"/>
</bean>

RequestMappingHandlerAdapter:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/plain;charset=UTF-8</value>
</list>
</property>
</bean>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<constructor-arg ref="marshaller"/>
</bean>
</list>
</property>
<property name="customArgumentResolvers">
<bean class="org.format.demo.support.resolve.FormModelMethodArgumentResolver"/>
</property>
<property name="webBindingInitializer">
<bean class="org.format.demo.support.binder.MyWebBindingInitializer"/>
</property>
<property name="order" value="-1"/>
</bean>

当我们配置了annotation-driven以及这两个bean的时候。Spring容器就有了2个RequestMappingHandlerAdapter和2个RequestMappingHandlerMapping。

DispatcherServlet内部有HandlerMapping(RequestMappingHandlerMapping是其实现类)集合和HandlerAdapter(RequestMappingHandlerAdapter是其实现类)集合。


private List<HandlerMapping> handlerMappings; private List<HandlerAdapter> handlerAdapters;

我们看下这两个集合的初始化代码:

很明显使用了我们提到的OrderComparator比较器进行了排序。

下面我们看下annotation-driven代码配置的RequestMappingHandlerMapping和RequestMappingHandlerAdapter。

RequestMappingHandlerMapping默认会设置order属性为0,RequestMappingHandlerAdapter没有设置order属性。

我们进入RequestMappingHandlerMapping和RequestMappingHandlerAdapter代码里面看看它们的order属性是如何定义的。

AbstractHandlerMethodAdapter是RequestMappingHandlerAdapter的父类。

AbstractHandlerMapping是RequestMappingHandlerMapping的父类。

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

PS:

如果配置了<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。

这点读者可自行测试。

在多个视图解释器中,也运用到了Ordered接口。

总结

了解了Spring中Ordered接口的意义,并从实践中分析了这个接口的运用。

这个Ordered接口也是楼主研究SpringMVC配置多个视图解析器的时候发现的,以前的时候没怎么注意,一直认为自定义配置的RequestMappingHandlerAdapter优先级会高一点,会覆盖<mvc:annotation-driven />配置的RequestMappingHandlerAdapter。 如今已明白优先级的问题。

希望这篇文章能帮助读者了解Ordered接口。

文中难免有错误,希望读者能够指明出来。

Spring中Ordered接口简介的更多相关文章

  1. 转:spring中InitailizingBean接口的简单理解

    转自:https://www.cnblogs.com/wxgblogs/p/6849782.html spring中InitializingBean接口使用理解   InitializingBean接 ...

  2. spring中InitializingBean接口使用理解

    InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法. 测试程序如下: imp ...

  3. Spring 中 IoC 容器简介

    IoC 是一种通过描述来生成或者获取对象的技术,可以说 Spring 是一种基于 IoC 容器编程的框架 在一个系统中可以生成各种对象,并且这些对象都需要进行管理.为了描述这些对象关系,我们需要一个容 ...

  4. spring中ApplicationContextAware接口描述

    项目中使用了大量的工厂类,采用了简单工厂模式: 通过该工厂类可以获取指定的处理器bean,这些处理器bean我们是从spring容器中获取的,如何获取,是通过实现ApplicationContextA ...

  5. spring中InitializingBean接口使用理解(转)

    InitializingBean接口为bean提供了初始化方法的方式,它只包括afterPropertiesSet方法,凡是继承该接口的类,在初始化bean的时候会执行该方法. 测试程序如下: imp ...

  6. spring(五):spring中Aware接口的使用

    spring中自定义组件需要使用spring的底层组件时,可以通过自定义组件实现相关XxxAware接口,重写其中的方法进而实现 例如:自定义一个组件,该组件中需要使用ApplicationConte ...

  7. Spring中的接口BeanFactory和FactoryBean的学习

    BeanFactory: 相当于对象工厂,可以获取对象的实例以及相应的属性.BeanFactory定义了IOC容器的最基本形式,并提供了IOC容器应遵守的的最基本的接口,也就是Spring IOC所遵 ...

  8. Spring 中的接口知识整理

    本想每个小知识一篇随笔,但是那样,看起来有些单薄,所以,就放在一片文章里了.而且,以后还会慢慢在最后不断的追加. 目录: FactoryBean BeanPostProcessor 1.Factory ...

  9. spring中ApplicationContextAware接口使用理解

    一.这个接口有什么用?当一个类实现了这个接口(ApplicationContextAware)之后,这个类就可以方便获得ApplicationContext中的所有bean.换句话说,就是这个类可以直 ...

随机推荐

  1. Arch Linux 简易打包指南

    本文时代久远,请参阅更可靠的:Arch User Repository (简体中文) - 分享和维护软件包 这两天给 Kreogist µ 打 Arch Linux 包,照着 wiki 跟着搞,同时在 ...

  2. updateEasyuiTab

    //tabContainer:easyui-tabs或者id,title名称 this.updateEasyuiTab = function (tabContainer, outTitle, outU ...

  3. (转)linux下cp目录时排除一个或者多个目录的实现方法

    原文链接:http://www.jb51.net/LINUXjishu/88971.html 说明:/home目录里面有data目录,data目录里面有a.b.c.d.e五个目录,现在要把data目录 ...

  4. create()创建的控件不能映射消息函数的解决

    有时,使用create()在运行时创建的控件不能将消息映射到父窗口内,此时需要使用消息转发的机制,主要原理:注册一个全局的消息,针对接收消息的控件编写继承类,在该继承类中响应消息,并将已注册的全局消息 ...

  5. Http请求中Content-Type讲解以及在Spring MVC中的应用

    引言: 在Http请求中,我们每天都在使用Content-type来指定不同格式的请求信息,但是却很少有人去全面了解content-type中允许的值有多少,这里将讲解Content-Type的可用值 ...

  6. jxl 处理 Excel 样式

    jxl 能够操作的 excel 样式: 1. Workbook的格式设置(代表一个excel文件) 2. Sheet的格式设置(代表一个表格) 3. Cell的格式设置(代表一个单元格) PS:此jx ...

  7. 再次完善了 WASPCN for Matlab

    前段时间有多个网友询问在64位Matlab中如何使用WASPCN(水和蒸汽性质计算软件)的方法,一直没能给出解决方案. 最近自己有个项目也需要在64位Matlab中如何使用WASPCN(水和蒸汽性质计 ...

  8. Android应用程序Monkey测试

    Monkey是Android SDK中附带的一个测试工具:Monkey用于进行压力测试,软件开发人员结合monkey打印日志和系统日志,解决测试中出现的问题. Monkey测试的特点:所有事件都是随机 ...

  9. window.innerWidth、document.body.clientWidth和html的大小的区别

    首先,我们知道document.body指向的就是body元素,如此,我们就可以以document.body来获取body的大小.何以知之?如下代码: var body = document.quer ...

  10. Win10专业版激活方法可查版本

    Win10专业版激活步骤 ------安装Win10专业版,请win+R,键入winver回车,可查看版本------ 1.点击左下角windows按钮,找到设置并打开,依次点击"更新和安全 ...