優秀開源框架的擴充套件機制實現
一些優秀的開源框架,總會給開發者留一個後門,方便實現對其中某一塊功能,根據公司自身生態進行有效的擴充套件,比如Neflix開源的Hystrix,其實Hystrix的程式碼寫的真的很好,除了RxJava那部分晦澀的實現。
在Hystrix中的外掛實現中,提供了5個擴充套件點,通過實現這些外掛介面,可以很好的結合公司內部框架進行使用,比如資料埋點、動態配置等等,下面以事件通知介面為例子,看看Hystrix是如何實現的。
public HystrixEventNotifier getEventNotifier() { if (notifier.get() == null) { // check for an implementation from Archaius first Object impl = getPluginImplementation(HystrixEventNotifier.class); if (impl == null) { // nothing set via Archaius so initialize with default notifier.compareAndSet(null, HystrixEventNotifierDefault.getInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned } else { // we received an implementation from Archaius so use it notifier.compareAndSet(null, (HystrixEventNotifier) impl); } } return notifier.get(); }
通過 getEventNotifier
方法獲取事件通知器,當然了,一開始是沒有初始化的,先嚐試使用 getPluginImplementation
方法,看看能不能拿到,拿不到就使用本地預設的實現。
private <T> T getPluginImplementation(Class<T> pluginClass) { T p = getPluginImplementationViaProperties(pluginClass, dynamicProperties); if (p != null) return p; return findService(pluginClass, classLoader); }
這裡,Hystrix還提供了另外一種實現,很簡單,就不解釋了,這裡的重點是 findService
實現。
private static <T> T findService(Class<T> spi,ClassLoader classLoader) throws ServiceConfigurationError { ServiceLoader<T> sl = ServiceLoader.load(spi, classLoader); for (T s : sl) { if (s != null) return s; } return null; }
其實,這裡的實現是使用Java內建的SPI機制,SPI是什麼?
SPI 全稱為 Service Provider Interface),是一種服務提供發現機制,通過 ServiceLoader
類的load方法,可以自動找到實現對應介面的實現類,為了更清晰的瞭解其中原理,可以去看看load方法的原始碼實現。
一個大概的過程是:load方法會嘗試在classpath下META-INF/services/資料夾下查詢一個檔案,其中檔名是介面的全限定名。

如上圖所述, CacheKeyFilter
是一個介面,在這個檔案中,需要指定介面實現類的全限定名。

當然了,你也可以換行指定多個,找到這些實現類之後,會通過反射機制,即 class.newInstance()
進行例項化,這就要求實現類需要有無參建構函式,
通過這種方式,我們就可以愉快的對開源框架所提供的介面進行擴充套件,加入各種騷操作,還不動手試試?