Spring中Ordered接口簡介
前言
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接口
轉自:http://www.cnblogs.com/fangjian0423/p/spring-Ordered-interface.html
Spring中Ordered接口簡介