溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java中SPI 機(jī)制的原理是什么

發(fā)布時(shí)間:2021-06-16 14:23:24 來(lái)源:億速云 閱讀:269 作者:Leah 欄目:編程語(yǔ)言

Java中SPI 機(jī)制的原理是什么,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

什么是 SPI

在具體分析之前還是先了解下 SPI 是什么?

首先它其實(shí)是 Service provider interface 的簡(jiǎn)寫(xiě),翻譯成中文就是服務(wù)提供發(fā)現(xiàn)接口。

不過(guò)這里不要被這個(gè)名詞搞混了,這里的服務(wù)發(fā)現(xiàn)和我們常聽(tīng)到的微服務(wù)中的服務(wù)發(fā)現(xiàn)并不能劃等號(hào)。

就如同上文提到的對(duì) IOC 容器的多種實(shí)現(xiàn)方式 A、B、C(可以把它們理解為服務(wù)),我需要在運(yùn)行時(shí)知道應(yīng)該使用哪一種具體的實(shí)現(xiàn)。

其實(shí)本質(zhì)上來(lái)說(shuō)這就是一種典型的面向接口編程,這一點(diǎn)在我們剛開(kāi)始學(xué)習(xí)編程的時(shí)候就被反復(fù)強(qiáng)調(diào)了。

SPI 實(shí)踐

接下來(lái)我們來(lái)如何來(lái)利用 SPI 實(shí)現(xiàn)剛才提到的可拔插 IOC 容器。

既然剛才都提到了 SPI 的本質(zhì)就是面向接口編程,所以自然我們首先需要定義一個(gè)接口:

Java中SPI 機(jī)制的原理是什么

其中包含了一些 Bean 容器所必須的操作:注冊(cè)、獲取、釋放 bean。

為了讓其他人也能實(shí)現(xiàn)自己的 IOC 容器,所以我們將這個(gè)接口單獨(dú)放到一個(gè) Module 中,可供他人引入實(shí)現(xiàn)。

Java中SPI 機(jī)制的原理是什么

所以當(dāng)我要實(shí)現(xiàn)一個(gè)單例的 IOC 容器時(shí),我只需要新建一個(gè) Module 然后引入剛才的模塊并實(shí)現(xiàn) CicadaBeanFactory 接口即可。

當(dāng)然其中最重要的則是需要在 resources 目錄下新建一個(gè) META-INF/services/top.crossoverjie.cicada.base.bean.CicadaBeanFactory 文件,文件名必須得是我們之前定義接口的全限定名(SPI 規(guī)范)。

Java中SPI 機(jī)制的原理是什么

其中的內(nèi)容便是我們自己實(shí)現(xiàn)類(lèi)的全限定名:

top.crossoverjie.cicada.bean.ioc.CicadaIoc

可以想象最終會(huì)通過(guò)這里的全限定名來(lái)反射創(chuàng)建對(duì)象。

只不過(guò)這個(gè)過(guò)程 Java 已經(jīng)提供 API 屏蔽掉了:

public static CicadaBeanFactory getCicadaBeanFactory() {
    ServiceLoader<CicadaBeanFactory> cicadaBeanFactories = ServiceLoader.load(CicadaBeanFactory.class);
    if (cicadaBeanFactories.iterator().hasNext()){
      return cicadaBeanFactories.iterator().next() ;
    }

    return new CicadaDefaultBean();
  }

當(dāng) classpath 中存在我們剛才的實(shí)現(xiàn)類(lèi)(引入實(shí)現(xiàn)類(lèi)的 jar 包),便可以通過(guò) java.util.ServiceLoader 工具類(lèi)來(lái)找到所有的實(shí)現(xiàn)類(lèi)(可以有多個(gè)實(shí)現(xiàn)類(lèi)同時(shí)存在,只不過(guò)通常我們只需要一個(gè))。

一些都準(zhǔn)備好之后,使用自然就非常簡(jiǎn)單了。

<dependency>
    <groupId>top.crossoverjie.opensource</groupId>
    <artifactId>cicada-ioc</artifactId>
    <version>2.0.4</version>
  </dependency>

我們只需要引入這個(gè)依賴便能使用它的實(shí)現(xiàn),當(dāng)我們想換一種實(shí)現(xiàn)方式時(shí)只需要更換一個(gè)依賴即可。

這樣就做到了不修改一行代碼靈活的可拔插選擇 IOC 容器了。

SPI 的一些其他應(yīng)用

雖然平時(shí)并不會(huì)直接使用到 SPI 來(lái)實(shí)現(xiàn)業(yè)務(wù),但其實(shí)我們使用過(guò)的絕大多數(shù)框架都會(huì)提供 SPI 接口方便使用者擴(kuò)展自己的功能。

比如 Dubbo 中提供一系列的擴(kuò)展: Java中SPI 機(jī)制的原理是什么

同類(lèi)型的 RPC 框架 motan 中也提供了響應(yīng)的擴(kuò)展: Java中SPI 機(jī)制的原理是什么

他們的使用方式都和 Java SPI 非常類(lèi)似,只不過(guò)原理略有不同,同時(shí)也新增了一些功能。

比如 motan 的 spi 允許是否為單例等等。

再比如 MySQL 的驅(qū)動(dòng)包也是利用 SPI 來(lái)實(shí)現(xiàn)自己的連接邏輯。

Java中SPI 機(jī)制的原理是什么

看完上述內(nèi)容,你們掌握J(rèn)ava中SPI 機(jī)制的原理是什么的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI