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默认为trueif (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
public RequestMappingHandlerAdapter requestMappingHandlerAdapter()方法
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping()方法 分析代码可以知道:RequestMappingHandlerMapping默认会设置order属性为0,RequestMappingHandlerAdapter没有设置order属性。

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

RequestMappingHandlerMapping
// Ordered.LOWEST_PRECEDENCE只为Integer.MAX_VALUE
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupportimplements 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_VALUEprivate 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>

喜欢就关注我
图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/453396.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

将本地代码上传至github

注册github账号 https://github.com/ 安装git工具 https://git-for-windows.github.io 1.在github中创建一个项目 2.填写相应信息&#xff0c;点击create Repository name: 仓库名称 Description(可选): 仓库描述介绍 Public, Private : 仓库权限&#xff08;公开共享&#xff…

Java二十三设计模式之------工厂方法模式

一、工厂方法模式&#xff08;Factory Method&#xff09; 工厂方法模式有三种 1、普通工厂模式&#xff1a;就是建立一个工厂类&#xff0c;对实现了同一接口的一些类进行实例的创建。首先看下关系图&#xff1a; 举例如下&#xff1a;&#xff08;我们举一个发送邮件和短信的…

一元多项式乘法算法

我认为大致算法应该是这样的: 首先准备一个空的链表L。利用第一个多项式的的指针所指的节点数值乘以多项式二的每一项&#xff0c;将结果保存在链表L中。 然后将指向该节点的指针后移到下一个节点继续进行乘法运算&#xff0c;将所得结果加到L中&#xff08;这个操作已经在一…

Oracle 基础

为什么80%的码农都做不了架构师&#xff1f;>>> Oracle DB笔录&#xff0c;以后会不断Add&#xff0c;欢迎留言补充! --cmd.exe(你懂得!) --[1]多个数据库实例&#xff0c;切换选择DB后&#xff0c;登录操作 set ORACLE_SIDorcl --选择DB orcl(你的DB实例名) --可在…

Linux执行命令提示Password,linux expect远程自动登录以及执行命令

linux远程自动登录以及执行命令远程登录该自动登录的过程是通过shell里面expect实现的&#xff0c;类似相当于开了一个类似于cmd的命令段输出IP和密码。注意该脚本能够执行的前提是安装了expectyum install -y expect直接上脚本&#xff1a;#!/usr/bin/expect …

MyBatis 在xml文件中处理大于号小于号的方法

为什么80%的码农都做不了架构师&#xff1f;>>> 第一种方法&#xff1a;用转义字符&#xff08;注&#xff1a;对大小写敏感&#xff01; &#xff09; 用了转义字符把>和<替换掉&#xff0c;然后就没有问题了。 SELECT * FROM test WHERE 1 1 AND start_da…

linux 进程间读写锁,Linux系统编程—进程间同步

我们知道&#xff0c;线程间同步有多种方式&#xff0c;比如&#xff1a;信号量、互斥量、读写锁&#xff0c;等等。那进程间如何实现同步呢&#xff1f;本文介绍两种方式&#xff1a;互斥量和文件锁。##互斥量mutex我们已经知道了互斥量可以用于在线程间同步&#xff0c;但实际…

属性依赖注入

1.依赖注入方法 手动装配和自动装配 2.手动装配 2.1 基于xml装配 2.1.1 构造方法 <!-- 构造方法注入<constructor-arg>name:参数名type:类型value: --> <bean id"user" class"g_xml.constructor.User"><constructor-arg name"id…

MediaWiki安装配置(Linux)【转】

阅读目录 2.1 本例子的安装环境如下&#xff1a;转自&#xff1a;http://blog.csdn.net/gao36951/article/details/43965527 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 目录(?)[-] 1MediaWiki简介 2MediaWiki安装21 本例子的安装环境如…

在Asp.net core返回PushStream

最近用asp.net core webapi实现了一个实时视频流的推送功能&#xff0c;在Asp.net中&#xff0c;这个是通过PushStreamContent来实现的。 基于对asp.net core的知识&#xff0c;随手写了一个&#xff08;要求控制器继承自Controller基类&#xff09; [HttpGet] public async Ta…

顺序栈的代码实现

栈是一种限定只在表尾进行插入或删除操作的线性表&#xff0c;栈也是线性表。表头称为栈的底部,表尾称为栈的顶部,表为空称为空栈。 栈又称为后进先出的线性表,栈也有两种表示:顺序栈与链式栈。顺序栈是利用一组地址连续的存储单元。依次存放从栈底到栈顶的数据元素。 #includ…

eclipse+tomcat开发web程序

环境&#xff1a;windows 7Eclipse Java EE IDE for Web Developerstomcat 7.02 插件&#xff1a;tomcatPluginV321.zip 一.配置Tomcat插件 我们创建一个myplugins文件夹用于存放插件&#xff0c;myplugins位于D:/Program Files/J2EE目录下。eclipse安装路径为&#xff1a;D:/P…

LoadRunner参数包含逗号

loadrunner的参数以逗号区分&#xff0c; 如果参数本身包含逗号&#xff0c;则会报错 使用","将逗号包起来即可&#xff0c;如下图 转载于:https://www.cnblogs.com/cherrysu/p/8507649.html

android studio发布项目到github

点击file setting ,打开对话框&#xff0c;如下&#xff0c;判断git是否安装成功 选择GitHub&#xff0c;填写github地址及密码 发布项目&#xff1a; 转载于:https://www.cnblogs.com/haihai88/p/8514683.html

linux系统pcb软件下载,开源PCB设计软件KiCad致力于下一个大版本的发布

KiCad仍然是PCB设计和其他功能的领先开源电子设计套件。KiCad在2018年取得了成功&#xff0c;System76甚至使用了该软件作为与Thelio台式计算机一起设计的子板PCB的一部分&#xff0c;但展望未来&#xff0c;开发人员仍在努力开发6.0版本。KiCad 6.0发布方式将采用重新设计的GT…

Hibernate 学习(一)

一、Hibernate 简介 1、Hibernate 简介 Hibernate是一个开放源代码的对象关系映射(ORM)框架&#xff0c;它对JDBC进行了非常轻量级的对象封装&#xff0c;它将POJO与数据库表建立映射关系&#xff0c;是一个全自动的orm框架&#xff0c;hibernate可以自动生成SQL语句&#xff0…

矩阵的压缩存储

5.3 矩阵的压缩存储 矩阵是很多科学与工程计算问题中研究的数学对象&#xff0c;在此&#xff0c;我们讨论如何存储矩阵的元&#xff0c;从而使矩阵的各种运算能有效第进行。对于一个矩阵结构显然用一个二维数组来表示是非常恰当的&#xff0c;但在有些情况下&#xff0c;比如常…

网络工程师还要学linux吗,网络工程师要学什么

想成为一个优秀的网络工程师&#xff0c;要学什么&#xff0c;怎么学呢?今天小编带你了解一下网络工程师到底要学什么。上篇我们讲到了“网络工程师发展方向”&#xff0c;列举了许多技术方向&#xff0c;那么我们该如何根据自己的定位选择学习哪些技术。重点是哪些&#xff0…

广义表及其存储方式简介

广义表&#xff08;Lists&#xff0c;又称列表&#xff09;是线性表的推广。线性表定义为n>0个元素a1,a2,a3,…,an的有限序列。线性表的元素仅限于原子项&#xff0c;原子是作为结构上不可分割的成分&#xff0c;它可以是一个数或一个结构&#xff0c;若放松对表元素的这种限…

Vue.js:路由

ylbtech-Vue.js&#xff1a;路由1.返回顶部 1、Vue.js 路由 本章节我们将为大家介绍 Vue.js 路由。 Vue.js 路由允许我们通过不同的 URL 访问不同的内容。 通过 Vue.js 可以实现多视图的单页Web应用&#xff08;single page web application&#xff0c;SPA&#xff09;。 Vue.…