基於 Spring & SPI 實現動態服務配置實踐
定義一個介面,如何優雅的根據一個介面來獲取該介面的實現類呢?
以 Site 國際化為例,一般是各個國家有各個國家的 Service,各個國際的 Service 由各個國家的 team 維護,那在統一框架下,如何實現獲取動態服務,由此 SPI 引入眼簾。
SPI - Service Provider Interface
SPI 全稱為(Service Provider Interface),是 JDK 內建的一種服務提供發現機制,它是一種動態替換髮現服務實現者的機制。簡單地理解,這是建立在面向介面程式設計下的一種為了使元件可擴充套件或動態變更實現的規範。
常見的類 SPI 的設計有 JDBC、JNDI、JAXP 等,很多開源框架的內部實現也採用了 SPI。
1、在 mysql-connector-java-xxx.jar 中發現了 META-INF\services\java.sql.Driver 檔案
2、在 jcl-over-slf4j-xxxx.jar 中發現了 META-INF\services\org.apache.commons.logging.LogFactory 檔案
3、Dubbo 基於 SPI 實現了強大靈活的擴充套件機制
自定義 SPI
為什麼要自定義 SPI ?
在實際應用中,無論是 Java SPI 或是 Spring SPI,都無法服務與工程已有 Spring 容器進行整合。
舉個栗子:訂單 OrderService 的 Implement 是通過 SPI 方式建立的,可如果 OrderService 實現類中呼叫了 Spring 容器管理的商品 WareService,則會出現 null 異常,因為 OrderService 實現類的生命週期並沒有交給 Spring 容器管理。
基於此,我們可以自己實現一套邏輯,主要包括兩點:
-
1、載入 META-INF 目錄下的 spi 介面檔案
-
2、將例項化的 Bean 註冊到 Spring 的容器中
具體的實現,訪問 Github: https://github.com/linkedkeeper/spi-imp
Reference
https://www.cnkirito.moe/spi/
https://www.jianshu.com/p/7daa38fc9711