java中SPI服務提供者的接口使用總結
一:什么是SPI
SPI:“服務提供者的接口”,是一種服務發(fā)現(xiàn)機制
用于實現(xiàn)框架或庫的擴展點,允許在運行時動態(tài)地插入或更換組件實現(xiàn)。
它提供了一個框架(JDK1.6后ServiceLoader)來發(fā)現(xiàn)和加載服務實現(xiàn),使得軟件模塊能夠靈活地選擇和使用不同的服務提供商。
在java中通俗講就是:
- 對框架或第三方jar包提供者來說可制定規(guī)范,提供給開發(fā)者可擴展性
- 對開發(fā)者來說可以根據(jù)需要輕松替換框架或第三方jar包中提供了SPI機制的接口的實現(xiàn)
在AJ-Captcha與Nacos中均提供了SPI擴展。
二:java SPI示例
1.SPI服務提供方
SPI服務提供方架構圖:
定義接口規(guī)范:
public interface SpiService { /** * 呼叫方式 */ void call(); }
加載具體的服務實現(xiàn):
package com.lmy.config; import com.lmy.service.SpiService; import java.util.ArrayList; import java.util.List; import java.util.ServiceLoader; /** * @author : lmy * @date : 2024/9/14 上午 11:35 * 加載具體的服務實現(xiàn) */ public class SpiServiceLoader { private static volatile SpiServiceLoader LOADER; private final SpiService spiService; private final List<SpiService> spiServiceList; /** * 加載服務 * */ private SpiServiceLoader() { ServiceLoader<SpiService> loader = ServiceLoader.load(SpiService.class); List<SpiService> list = new ArrayList<>(); for (SpiService spiService : loader) { list.add(spiService); } spiServiceList = list; if (!list.isEmpty()) { // 取第一個 spiService = list.get(0); } else { spiService = null; } } /** * SpiServiceLoader 單例加載 * */ public static SpiServiceLoader getLOADER() { if (LOADER == null) { synchronized (SpiServiceLoader.class) { if (LOADER == null) { LOADER = new SpiServiceLoader(); } } } return LOADER; } public void call(){ if(spiServiceList.isEmpty()){ System.out.println("SpiService服務未加載!"); }else { SpiService spiService = spiServiceList.get(0); spiService.call(); } } }
默認實現(xiàn):
package com.lmy.service.impl; import com.lmy.service.SpiService; /** * @author : lmy * @date : 2024/9/14 上午 10:58 * 默認實現(xiàn) */ public class SpiServiceImpl implements SpiService { @Override public void call() { System.out.println("默認手機呼叫"); } }
指定服務實現(xiàn)方式:
須在resource下創(chuàng)建META-INF.services,文件名為接口全限定類名,配置為需要被加載的接口實現(xiàn)類的全限定類名
com.lmy.service.impl.SpiServiceImpl
項目打包發(fā)布本地:
2.SPI服務應用方開發(fā)者
開發(fā)者引入jar包使用服務:
<dependency> <groupId>com.lmy</groupId> <artifactId>SPI-interface</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
package com.lmy.Spi; import com.lmy.config.SpiServiceLoader; import org.junit.Test; /** * @author : lmy * @date : 2024/9/14 上午 11:48 */ public class SpiTest { @Test public void spiTest () { SpiServiceLoader loader = SpiServiceLoader.getLOADER(); loader.call(); } }
執(zhí)行結果:
開發(fā)者根據(jù)需要擴展替換為自己的服務實現(xiàn):
package com.lmy.Spi.service; import com.lmy.service.SpiService; /** * @author : lmy * @date : 2024/9/14 下午 2:09 */ public class SpiServiceNewImpl implements SpiService { @Override public void call() { System.out.println("衛(wèi)星直呼"); } }
com.lmy.Spi.service.SpiServiceNewImpl
執(zhí)行結果:
三:JavaSPI 機制的核心-ServiceLoader
上面代碼可見是通過ServiceLoader 去加載具體的服務實現(xiàn)的
ServiceLoader 是從JDK1.6 開始提供的一個類,用于加載服務提供者。
進入源碼可見:
其中 String PREFIX = “META-INF/services/”;
這個就是JDK的SPI功能規(guī)定的具體服務實現(xiàn)的配置信息文件所在的目錄 META-INF/services/
JDK的SPI規(guī)定 服務實現(xiàn)者需要在 META-INF/services/ 目錄下 新建文件名為 SPI接口全限定類名的文件
文件內(nèi)容為 服務實現(xiàn)者需要被加載的具體類的全限定類名
到此這篇關于java中SPI服務提供者的接口使用總結的文章就介紹到這了,更多相關java spi詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MyBatis-Plus多表聯(lián)合查詢并且分頁(3表聯(lián)合)
這篇文章主要介紹了MyBatis-Plus多表聯(lián)合查詢并且分頁(3表聯(lián)合),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-08-08SpringCloud Zuul在何種情況下使用Hystrix及問題小結
這篇文章主要介紹了SpringCloud Zuul在何種情況下使用Hystrix 及問題小結,感興趣的朋友跟隨小編一起看看吧2018-11-11idea中使用SonarLint進行代碼規(guī)范檢測及使用方法
這篇文章主要介紹了idea中使用SonarLint進行代碼規(guī)范檢測,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08使用java實現(xiàn)http多線程斷點下載文件(一)
Java 多線程斷點下載文件基本原理:利用URLConnection獲取要下載文件的長度、頭部等相關信息,并設置響應的頭部信息,本文將詳細介紹,需要了解更多的朋友可以參考下2012-12-12Java實現(xiàn)批量導入excel表格數(shù)據(jù)到數(shù)據(jù)庫中的方法
這篇文章主要介紹了Java實現(xiàn)批量導入excel表格數(shù)據(jù)到數(shù)據(jù)庫中的方法,結合實例形式詳細分析了java導入Excel數(shù)據(jù)到數(shù)據(jù)庫的具體步驟與相關操作技巧,需要的朋友可以參考下2017-10-10