簡介
SPI(Service Provider Interface)是JDK內建的服務提供發現機制,可以用來啟用框架擴充和取代元件,主要用於框架中開發,例如Dubbo、Spring、Common-Logging,JDBC等採用SPI機制,針對同一介面採用不同的實作提供給不同的用戶,從而提高了框架的擴展性。
Java SPI實作
Java內建的SPI透過java.util.ServiceLoader類別解析classPath和jar套件的META-INF/services/目錄下的以介面全限定名命名的文件,並載入該文件中指定的介面實作類,以此完成呼叫。
範例說明
建立動態介面
public interface VedioSPI { void call(); }
實作類別1
public class Mp3Vedio implements VedioSPI { @Override public void call() { System.out.println("this is mp3 call"); } }
實作類別2
public class Mp4Vedio implements VedioSPI { @Override public void call() { System.out.println("this is mp4 call"); } }
在專案的source目錄下新建META-INF/services/目錄下,建立com.skywares.fw.juc.spi.VedioSPI檔。
相關測試
public class VedioSPITest { public static void main(String[] args) { ServiceLoader<VedioSPI> serviceLoader =ServiceLoader.load(VedioSPI.class); serviceLoader.forEach(t->{ t.call(); }); } }
說明:Java實作spi是透過ServiceLoader來尋找服務提供的工具類別。
運行結果
源碼分析
#上述只是透過簡單的範例來實現下java的內建的SPI功能。其實作原理是ServiceLoader是Java內建的用於查找服務提供介面的工具類,透過呼叫load()方法實作對服務提供介面的查找,最後遍歷來逐個存取服務提供介面的實作類別。
從原始碼可以發現:
ServiceLoader類別本身實作了Iterable介面並實作了其中的iterator方法,iterator方法的實作中呼叫了LazyIterator這個內部類別中的方法,解析完服務提供介面檔案後最終結果放在了Iterator中返回,並不支援服務提供介面實作類別的直接存取。
所有服務提供介面的對應檔案都是放置在META-INF/services/目錄下,final類型決定了PREFIX目錄不可變更。
雖然java提供的SPI機制的想法非常好,但是也存在著相應的弊端。具體如下:
Java內建的方法方式只能透過遍歷來取得
服務提供介面必須放到META-INF/services/目錄下。
針對java的spi存在的問題,Spring的SPI機制沿用的SPI的思想,但對其進行擴展和優化。
Spring SPI
Spring SPI沿用了Java SPI的設計思想,Spring採用的是spring.factories方式實現SPI機制,可以在不修改Spring源碼的前提下,提供Spring框架的擴展性。
Spring範例
定義介面
public interface DataBaseSPI { void getConnection(); }
相關實作
#DB2实现 public class DB2DataBase implements DataBaseSPI { @Override public void getConnection() { System.out.println("this database is db2"); } } #Mysql实现 public class MysqlDataBase implements DataBaseSPI { @Override public void getConnection() { System.out.println("this is mysql database"); } }
1.在專案的META-INF目錄下,新增spring.factories檔案
2.填寫相關的介面信息,內容如下
com.skywares.fw.juc.springspi.DataBaseSPI = com.skywares.fw .juc.springspi.DB2DataBase, com.skywares.fw.juc.springspi.MysqlDataBase
說明多個實作採用逗號分隔。
相關測試類別
public class SpringSPITest { public static void main(String[] args) { List<DataBaseSPI> dataBaseSPIs =SpringFactoriesLoader.loadFactories(DataBaseSPI.class, Thread.currentThread().getContextClassLoader()); for(DataBaseSPI datBaseSPI:dataBaseSPIs){ datBaseSPI.getConnection(); } } }
輸出結果
#從範例中我們看出,Spring 採用spring.factories實作SPI與java實現SPI非常相似,但是spring的spi方式針對java的spi進行的相關優化具體內容如下:
Java SPI是一個服務提供接口對應一個配置文件,配置文件中存放當前介面的所有實作類,多個服務提供介面對應多個設定文件,所有配置都在services目錄下;
#Spring factories SPI是一個spring.factories設定檔存放多個介面及對應的實作類,以介面全限定名作為key,實作類別作為value來配置,多個實作類別用逗號隔開,僅spring.factories一個設定檔。
那麼spring是如何透過載入spring.factories來實現SpI的呢?我們可以透過原始碼來進一步分析。
原始碼分析
#:loadFactoryNames解析spring.factories檔案中指定介面的實作類別的全限定名,具體實作如下:
說明: 取得所有jar套件中META-INF/spring.factories檔案路徑,以列舉值返回。遍歷spring.factories檔案路徑,逐一載入解析,整合factoryClass型別的實作類別名稱,取得到實作類別的全類別名稱後進行類別的實例話操作,其相關原始碼如下:
#說明:實例化是透過反射來實現對應的初始化。
以上是SpringBoot的SPI機制怎麼實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Dreamweaver CS6
視覺化網頁開發工具

WebStorm Mac版
好用的JavaScript開發工具