Java的SPI機制實例詳解
SPI的全名為Service Provider Interface.普通開發人員可能不熟悉,因為這個是針對廠商或者插件的。在java.util.ServiceLoader的文檔里有比較詳細的介紹。究其思想,其實是和"Callback"差不多。“Callback”的思想是在我們調用API的時候,我們可以自己寫一段邏輯代碼,傳入到API里面,API內部在合適的時候會調用它,從而實現某種程度的“定制”。
典型的是Collections.sort(List<T> list,Comparator<? super T> c)這個方法,它的第二個參數是一個實現Comparator接口的實例。我們可以根據自己的排序規則寫一個類,實現此接口,傳入此方法,那么這個方法就會根據我們的規則對list進行排序。
把這個思想擴展開來,我們用SPI來重新實現上面的例子。客戶把自己的排序規則寫成一個類,并且打包成Jar文件,這個Jar文件里面必須有META-INF目錄,其下又有services目錄,其下有一個文本文件,文件名即為接口的全名:
1
2
3
4
|
java.util.Comparator。 --META-INF --services --java.util.Comparator |
文件內容只有一行:
1
|
com.company1.ComparatorProvider |
這一行是你實現了Comparator接口的類的全名,它的代碼如下:
1
2
3
4
5
6
7
8
9
10
|
package com.company1; import java.util.Comparator; import com.mycompany.myapp.MyItem; public class ComparatorProvider implements Comparator<MyItem>{ @Override public int compare(MyItem o1, MyItem o2) { //依據name排序 return o1.getName().compareTo(o2.getName()); } } |
編譯打包后,把它放到你的主程序的class path里。下面是你的主程序:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
//從class path中所有Jar的META-INF目錄中搜索,找到合適的類并加載。 private static ServiceLoader<Comparator> serviceLoader = ServiceLoader.load(Comparator. class ); public static void main(String[] args) { List<MyItem> myList = new ArrayList<MyItem>(); myList.add( new MyItem( 2 , "c" , "hhh" )); myList.add( new MyItem( 3 , "k" , "ooo" )); myList.add( new MyItem( 4 , "d" , "ppp" )); myList.add( new MyItem( 5 , "b" , "ggg" )); showList(myList); Collections.sort(myList,getCompartor()); showList(myList); } @SuppressWarnings ( "unchecked" ) private static Comparator<MyItem> getCompartor() { for (Comparator service : serviceLoader) { return (Comparator<MyItem>)service; } return null ; } |
要注意的是serviceLoader開始只是加載類,實例化要到第一次用的時候。類MyItem和方法showList并不重要,所以你不必在意。你可以按照這個規則,寫另外一個排序規則的Jar,隨時可以更換你的排序規則.
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
原文鏈接:http://mars914.iteye.com/blog/1283859