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這兩個類。
既然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介面。