首页 > 其他分享 >Spring核心接口之Ordered

Spring核心接口之Ordered

时间:2023-06-02 17:05:08浏览次数:37  
标签:Ordered int Spring 接口 public RequestMappingHandlerMapping RequestMappingHandlerA


一、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
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 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_spring


标签:Ordered,int,Spring,接口,public,RequestMappingHandlerMapping,RequestMappingHandlerA
From: https://blog.51cto.com/u_13538361/6404144

相关文章

  • 如何使用Spring管理Filter和Servlet
    在使用spring容器的web应用中,业务对象间的依赖关系都可以用context.xml文件来配置,并且由spring容器来负责依赖对象的创建。如果要在filter或者servlet中使用spring容器管理业务对象,通常需要使用WebApplicationContextUtils.getRequiredWebApplicationContext......
  • spring为什么注入接口而不是实现类?
    首先,一般使用接口是很常用并且有益的变成技术。其次,在spring中,你可以在运行过程中注入各种实现。一个很经典的情况就是在测试阶段,注入模拟的实现类。===1.网上说jdk动态代理基于实现接口。直接注入实现类会使aop失效。没有cglib可能真的就失效了。2.解耦。假如有一天实现类的名......
  • springboot项目rabbitmq消费者消费json格式的String,出现无限循环抛出No method found
    转:springboot项目rabbitmq消费者消费json格式的String,出现无限循环抛出Nomethodfoundforclass[B     ......
  • [MyBatis]DAO层只写接口,不用写实现类
    团队开发一个项目,由老大架了一个框架,遇到了DAO层不用写接口了,我也是用了2次才记住这个事的,因为自己一直都是习惯于写DAO层的实现类,所以,习惯性的还是写了个实现类。于是遇到错误了。找不到那个方法。问了团队的人才知道,方法名和Mapper中配置的id名必须一样。实现:一、配置Spring集......
  • 【电商api接口淘宝系列分享】获得商品评论+获得淘宝店铺详情演示示例
    商品评论是电商平台中一个非常重要的功能,对于商家和消费者都具有重要的意义。以下是商品评论的重要性:帮助其他消费者做出购买决策:消费者在购物前往往会查看其他消费者对商品的评价,通过评论得知商品的好、坏之处,从而做出更准确的购买决策。提供商家改进产品的意见和建议:通过......
  • 【电商api接口系列分享】按关键字搜索商品演示示例
     在电商平台中,关键词推荐是提高用户购物体验和销售业绩的一个重要手段。它的重要性体现在以下几个方面:提升购物体验:通过关键词推荐,电商平台可以根据用户的搜索意图和行为来向其推荐相关的商品。这样可以帮助用户更快地找到自己需要的商品,提高购物体验和满意度。增加销售......
  • SpringMVC大文件分片上传/多线程上传
    ​ javaweb上传文件上传文件的jsp中的部分上传文件同样可以使用form表单向后端发请求,也可以使用ajax向后端发请求    1.通过form表单向后端发送请求         <formid="postForm"action="${pageContext.request.contextPath}/UploadServlet"method="post"e......
  • unordered_map、unordered_set使用
    unordered_map头文件#include<iostream>#include<unordered_map>usingnamespacestd;增删查改unordered_map底层实现为哈希表,增删效率与查找效率都是O(1)增加元素emplace(key,value)insert(pair<T,T>p)数组修改法//unordered_map三种增加元素的方式// insert(......
  • linux sh脚本启动springboot
    1、restart.sh#!/bin/bashAPP_NAME=xxxxx.jar#定义JAVA程序名LOG_FILE="$APP_NAME.log"#定义日志文件名称#查询进程并终止PID=`ps-ef|grep$APP_NAME|grep-vgrep|awk'{print$2}'`kill-9$PIDecho"$APP_NAME的进程$PID已经终止"#启动jar包,指......
  • 如果还不懂如何使用 Consumer 接口,来青岛我当面给你讲!
    背景没错,我还在做XXXX项目,还在与第三方对接接口,不同的是这次是对自己业务逻辑的处理。在开发过程中我遇到这么一个问题:表结构:一张主表A,一张关联表B,表A中存储着表B记录的状态。场景:第一步创建主表数据,插入A表;第二步调用第三方接口插入B表同时更新A表的状态。此时大家应该都......