1、Ordered接口介紹
Spring中提供了一個Ordered接口。從單詞意思就知道Ordered接口的做用就是用來排序的。
Spring框架是一個大量使用策略設計模式的框架,這意味着有不少相同接口的實現類,那麼一定會有優先級的問題。因而Spring就提供了Ordered這個接口,來處理相同接口實現類的優先級問題。java
2、Ordered接口分析
一、Ordered接口的定義:spring
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最低級(數值最大)。數組
二、OrderComparator類:實現了Comparator接口的一個比較器。mvc
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); } }
}app
提供了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值,值越低,優先級越高。測試
3、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是其實現類)集合。this
//RequestMappingHandlerMapping集合 private List<HandlerMapping> handlerMappings; //HandlerAdapter集合 private List<HandlerAdapter> handlerAdapters;
在仔細看下DispatcherServlet類的private void initHandlerMappings(ApplicationContext context)方法能夠看到以下代碼:lua
//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。
4、應用
一、定義接口
import java.util.Map; import org.springframework.core.Ordered; public interface Filter extends Ordered{ public void doFiler(Map<String, String> prams); }
二、實現接口
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("權限控制"); } }
三、測試進行排序
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); } }
四、配置文件
<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>
喜歡就關注我