Spring核心接口之Ordered

1、Ordered接口介紹html

Spring中提供了一個Ordered接口。從單詞意思就知道Ordered接口的做用就是用來排序的。java

Spring框架是一個大量使用策略設計模式的框架,這意味着有不少相同接口的實現類,那麼一定會有優先級的問題。因而Spring就提供了Ordered這個接口,來處理相同接口實現類的優先級問題。spring

 

2、Ordered接口分析設計模式

一、Ordered接口的定義:數組

public interface Ordered {mvc

/**app

 * Useful constant for the highest precedence value.框架

 * @see java.lang.Integer#MIN_VALUE測試

 */this

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接口的一個比較器。

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值,值越低,優先級越高。

 

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是其實現類)集合。

//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。

 

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>

喜歡就關注我:

 

參考:http://www.wang1314.com/doc/topic-1568135-1.html

相關文章
相關標籤/搜索