SPI都不知道?還敢說懂Dubbo?面試官懟得我啞口無言啊
為什麼要講SPI呢?因為在Dubbo就用到了SPI機制,所以掌握了這部分對於後面的學習還是很有幫助的。
SPI ,全稱為 Service Provider Interface,是一種服務發現機制。它透過在ClassPath路徑下的META-INF/services資料夾查詢檔案,自動載入檔案裡所定義的類。這一機制為很多框架擴充套件提供了可能,比如在Dubbo、JDBC中都使用到了SPI機制。我們先透過一個很簡單的例子來看下它是怎麼用的。
案例介紹
先定義介面專案
然後建立一個擴充套件的實現,先匯入上面介面專案的依賴
然後建立介面的實現
/** * SPI:MySQL對於 baseURL 的一種實現 */public class MySQLData implements BaseData { @Override public void baseURL() { System。out。println(“mysql 的擴充套件實現。。。。”); }}
然後在resources目錄下建立 META-INF/services 目錄,然後在目錄中建立一個檔案,名稱必須是定義的介面的全類路徑名稱。然後在檔案中寫上介面的實現類的全類路徑名稱。
同樣的再建立一個案例
然後在測試的專案中測試
public static void main(String[] args) { ServiceLoader
根據不同的匯入,執行的邏輯會有不同
原始碼檢視
ServiceLoader
首先來看下ServiceLoader的類結構
// 配置檔案的路徑 private static final String PREFIX = “META-INF/services/”; // 載入的服務 類或者介面 private final Class service; // 類載入器 private final ClassLoader loader; // 訪問許可權的上下文物件 private final AccessControlContext acc; // 儲存已經載入的服務類 private LinkedHashMap
load
load方法建立了一些屬性,重要的是例項化了內部類,LazyIterator。
public final class ServiceLoader implements Iterable private ServiceLoader(Class svc, ClassLoader cl) { //要載入的介面 service = Objects。requireNonNull(svc, “Service interface cannot be null”); //類載入器 loader = (cl == null) ? ClassLoader。getSystemClassLoader() : cl; //訪問控制器 acc = (System。getSecurityManager() != null) ? AccessController。getContext() : null; reload(); } public void reload() { //先清空 providers。clear(); //例項化內部類 LazyIterator lookupIterator = new LazyIterator(service, loader); }}
查詢實現類和建立實現類的過程,都在LazyIterator完成。當我們呼叫iterator。hasNext和iterator。next方法的時候,實際上呼叫的都是LazyIterator的相應方法。
private class LazyIterator implements Iterator{ Class service; ClassLoader loader; Enumeration
建立例項物件,當然,呼叫next方法的時候,實際呼叫到的是,lookupIterator。nextService。它透過反射的方式,建立實現類的例項並返回。
private class LazyIterator implements Iterator{ private S nextService() { //全限定類名 String cn = nextName; nextName = null; //建立類的Class物件 Class<?> c = Class。forName(cn, false, loader); //透過newInstance例項化 S p = service。cast(c。newInstance()); //放入集合,返回例項 providers。put(cn, p); return p; }}
看到這兒,我想已經很清楚了。獲取到類的例項,我們自然就可以對它為所欲為了!
影片介紹: