Java SPI_Service Provider Interfacehtml
咱們系統裏抽象的各個模塊,每每有不少不一樣的實現方案,好比日誌模塊的方案,xml解析模塊、jdbc模塊的方案等。面向的對象的設計裏,咱們通常推薦模塊之間基於接口編程,模塊之間不對實現類進行硬編碼。一旦代碼裏涉及具體的實現類,就違反了可拔插的原則,若是須要替換一種實現,就須要修改代碼。 java
爲了實如今模塊裝配的時候能不在程序裏動態指明,這就須要一種服務發現機制。java spi就是提供這樣的一個機制:爲某個接口尋找服務實現的機制。有點相似IOC的思想,就是將裝配的控制權移到程序以外,在模塊化設計中這個機制尤爲重要。編程
Java SPI的具體約定以下 :當服務的提供者,提供了服務接口的一種實現以後,在jar包的META-INF/services/目錄裏同時建立一個以服務接口命名的文件。該文件裏就是實現該服務接口的具體實現類。而當外部程序裝配這個模塊的時候,就能經過該jar包META-INF/services/裏的配置文件找到具體的實現類名,並裝載實例化,完成模塊的注入。 api
基於這樣一個約定就能很好的找到服務接口的實現類,而不須要再代碼裏制定。jdk提供服務實現查找的一個工具類:java.util.ServiceLoaderoracle
示例以下,使用Java SPI機制實現Compatator接口的服務實現。ide
package com.usoft; /** * Created by xinxingegeya on 15/12/29. */ public class MyItem { private String name; private int level; public MyItem(String name, int level) { this.name = name; this.level = level; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getLevel() { return level; } public void setLevel(int level) { this.level = level; } @Override public String toString() { return "MyItem{" + "level=" + level + ", name='" + name + '\'' + '}'; } }
Comparator實現一:模塊化
package com.usoft; import java.util.Comparator; /** * Created by xinxingegeya on 15/12/29. */ public class ComparatorProviderByLevel implements Comparator<MyItem> { @Override public int compare(MyItem o1, MyItem o2) { return o1.getLevel() - o2.getLevel(); } }
Comparator實現二:工具
package com.usoft; import java.util.Comparator; /** * Created by xinxingegeya on 15/12/29. */ public class ComparatorProviderByName implements Comparator<MyItem> { @Override public int compare(MyItem o1, MyItem o2) { return o1.getName().compareTo(o2.getName()); } }
classpath路徑下的META-INF/services路徑下創建以接口爲名的文件,java.util.Comparatorthis
#爲註釋編碼
#com.usoft.ComparatorProviderByName com.usoft.ComparatorProviderByLevel
Main方法,
package com.usoft; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.ServiceLoader; /** * Created by xinxingegeya on 15/12/29. */ public class Main { private static ServiceLoader<Comparator> serviceLoader = ServiceLoader .load(Comparator.class, Thread.currentThread().getContextClassLoader()); public static void main(String args[]) { List<MyItem> myList = new ArrayList<>(); myList.add(new MyItem("c", 2)); myList.add(new MyItem("a", 7)); myList.add(new MyItem("d", 4)); myList.add(new MyItem("b", 5)); // Collections.sort(myList, new Comparator<MyItem>() { // @Override // public int compare(MyItem o1, MyItem o2) { // return o1.getLevel() - o2.getLevel(); // } // }); Collections.sort(myList, getComparator()); showMyList(myList); } private static void showMyList(List<MyItem> list) { list.forEach(System.out::println); } private static Comparator<MyItem> getComparator() { for (Comparator<MyItem> comparator : serviceLoader) { System.out.println(comparator.getClass().getName()); return comparator; } throw new RuntimeException("comparator is not found"); } }
參考文獻:
http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html
=========END=========