最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA中的SPI思想介紹

 更新時間:2022年01月28日 16:17:54   作者:夏末?-?秋涼  
大家好,本篇文章主要講的是JAVA中的SPI思想介紹,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下

1. SPI介紹

SPI全稱Service Provider Interface,是Java提供的一套用來被第三方實現(xiàn)或者擴展的接口,其意義在于為某個接口尋找服務(wù)的實現(xiàn),主要應(yīng)用在框架中用來尋找組件,提高擴展性。

汽車制造是一個比較繁瑣的過程,通常的手段是先規(guī)定汽車各個零部件的生產(chǎn)規(guī)格,各個零部件廠商按照這種規(guī)則去生產(chǎn)合格的零部件。汽車生產(chǎn)商挑選合適的零部件去組裝以出產(chǎn)汽車。汽車某個零部件損壞也不用廢棄掉整個汽車,只需要更換組件即可。

SPI就是用來怎么去尋找汽車零部件的一種機制,生產(chǎn)規(guī)格就是接口的定義,零部件生產(chǎn)商生產(chǎn)零部件就是遵循接口提供具體的實現(xiàn),SPI挑選合適的組件進行組裝后完成特定的功能,當(dāng)某個組件存在漏洞或問題時可以在不改動代碼的前提下替換組件以提高擴展性。

2. SPI規(guī)則

SPI旨在為某個接口尋找服務(wù)的實現(xiàn),因此在設(shè)計初期就要規(guī)定好組件的接口,JAVA的SPI機制使用步驟如下:

定義組件接口(生產(chǎn)規(guī)格)

實現(xiàn)組件接口(提供組件)

配置組件文件(查找組件)

反射實例調(diào)用(組裝工作)

3. SPI案例

在這里插入圖片描述

組件定義工程中定義組件開發(fā)的規(guī)范,即定義組件需要實現(xiàn)哪些接口組件A工程和組件B工程提供對組件的實現(xiàn),即實現(xiàn)組件定義的接口組件應(yīng)用工程挑選合適的組件進行組件的運用

3.1 組件的定義

在【commons-api】工程中定義組件的規(guī)范,即定義接口,接口名稱為ComponentService,內(nèi)容如下:

public interface ComponentService
{
    /**
     * 獲取組件的名稱
     * @return 組件名稱
     */
    String getComponentName();
}

3.2 組件的實現(xiàn)

在【component-A】工程中按照組件定義的規(guī)范提供組件,即實現(xiàn)組件定義接口,類名稱為ComponentA,內(nèi)容如下:

public class ComponentA implements ComponentService
{
    /**
     * 組件名稱
     */
    private static final String COMPONENT_NAME = "組件A";

    @Override
    public String getComponentName()
    {
        return COMPONENT_NAME;
    }
}

按照JAVA的SPI規(guī)則在【component-A】工程的resource/META-INF/services資源目錄下新建文件,文件名稱為組件接口的全限定名,內(nèi)容為組件實現(xiàn)的全限定名

在這里插入圖片描述

在【component-B】工程中也提供對應(yīng)的組件實現(xiàn),類名稱為ComponentB,內(nèi)容如下:

public class ComponentB implements ComponentService
{
    /**
     * 組件名稱
     */
    private static final String COMPONENT_NAME = "組件B";

    @Override
    public String getComponentName()
    {
        return COMPONENT_NAME;
    }
}

同樣在【component-B】工程的resource/META-INF/services資源目錄下配置文件

在這里插入圖片描述

3.3 組件的選用

基于maven構(gòu)建的java工程使用pom文件來編排項目所需要的依賴組件,現(xiàn)在需要用到組件,并且我覺得A組件比B組件更適合我,如是在【component-application】工程的pom中我編排了組件A,內(nèi)容如下:

<dependencies>
    <dependency>
        <groupId>com.xxxx</groupId>
        <artifactId>component-A</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

在【component-application】工程中新建應(yīng)用程序啟動類來運用組件,類名稱為Main,內(nèi)容如下:

public class Main
{
    public static void main(String[] args)
    {
        // 加載組件
        ServiceLoader<ComponentService> components = ServiceLoader.load(ComponentService.class);
        for (ComponentService component : components)
        {
            // 運用組件:打印組件名稱
            System.out.println(component.getComponentName());
        }
    }
}

啟動【component-application】工程的Main類的main方法,結(jié)果如下:

在這里插入圖片描述

假如某一天我發(fā)現(xiàn)組件A存在很大漏洞,需要更換組件將組件A替換成組件B,只需要在【component-application】工程的pom中去掉組件A的依賴,導(dǎo)入組件B的依賴即可,pom內(nèi)容如下:

<dependencies>
    <dependency>
        <groupId>com.xxxx</groupId>
        <artifactId>component-B</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

無需修改【component-application】工程的具體使用細節(jié),就可以達到替換組件的目的,運行如下:

在這里插入圖片描述

4. SPI原理

JAVA提供的SPI機制主要依靠的是java.util.ServiceLoader類,從SPI案例中入手,進入ServiceLoader.load方法一探究竟。

在這里插入圖片描述

load方法最終會創(chuàng)建一個LazyIterator 的實例,看到Iterator大概就知道和迭代器有關(guān),繼續(xù)了解一下LazyIterator 是什么

在這里插入圖片描述

猜想得不錯,LazyIterator 和迭代器有關(guān),它是ServiceLoader的一個內(nèi)部類,實現(xiàn)了Iterator接口,那只需要重點關(guān)注Iterator接口定義的方法

public boolean hasNext()
public S next()

Iterator接口定義的hasNext方法用于判斷迭代的是否是否還有下一個元素,LazyIterator 的hasNext方法最終是調(diào)用的hasNextService方法,重點研究這個。

在這里插入圖片描述

通過類加載器獲取到指定目錄下的資源文件配置的組件實現(xiàn)的全限定名,存放在configs的一個容器變量中,有了組件實現(xiàn)的全限定名,后面多半就是反射生成對象返回了,繼續(xù)看一下LazyIterator 的next方法。LazyIterator的next方法主要邏輯是在nextService方法中,仔細分析一下

在這里插入圖片描述

和剛才的猜想一致,拿到了組件實現(xiàn)的全限定名通過Class.forName來生成組件對象,所以程序就通過for循環(huán)得到了對象可以進行調(diào)用。

5. SPI要求

java.util.ServiceLoader類是這樣來描述自己的

A simple service-provider loading facility.

一個簡單的服務(wù)提供者加載工具

The only requirement enforced by this facility is thatprovider classes must have a zero-argument constructor so that they can beinstantiated during loading

強制執(zhí)行的唯一要求是提供者類必須有一個無參的構(gòu)造函數(shù),以便它們可以在加載過程中實例化,從Class.forName生成實例對象就可以看出使用的是無參構(gòu)造

6. SPI應(yīng)用

? SPI的這種組件替換思想很容易讓人想到我們熟知的JDBC規(guī)范。JDBC是JAVA規(guī)定的應(yīng)用程序連接數(shù)據(jù)庫的標準,定義了連接數(shù)據(jù)庫的幾個接口,比如Connection、Statement、ResultSet。各個數(shù)據(jù)庫廠商提供自己的JDBC實現(xiàn),這就是我們所說的數(shù)據(jù)庫驅(qū)動。開發(fā)人員只需要關(guān)心如何使用JDBC的各個接口,不需要學(xué)習(xí)不同廠商的實現(xiàn),這就是面向接口編程。

JDBC編程分為四個步驟,SPI在驅(qū)動管理器DriverManager中得到了應(yīng)用

在這里插入圖片描述

Mysql驅(qū)動和SqlServer驅(qū)動都有SPI的配置

在這里插入圖片描述

在驅(qū)動管理器的loadInitialDrivers方法中就會通過SPI機制獲取可用的驅(qū)動,loadInitialDrivers方法會在靜態(tài)代碼塊中被調(diào)用。這里并沒有通過全限定名反射實例化,真正的驅(qū)動注冊是數(shù)據(jù)庫廠商提供的驅(qū)動類中通過靜態(tài)代碼塊將驅(qū)動注冊到驅(qū)動管理器中的registeredDrivers集合變量中的,以MySQL驅(qū)動為例:

在這里插入圖片描述

在這里插入圖片描述

在驅(qū)動管理器的getConnection方法中會遍歷SPI查找到的可用驅(qū)動,通過驅(qū)動獲取鏈接,直至鏈接獲取成功才返回。

在這里插入圖片描述

總結(jié)

到此這篇關(guān)于JAVA中的SPI思想介紹的文章就介紹到這了,更多相關(guān)JAVA SPI思想內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Atomikos + MybatisPlus解決多數(shù)據(jù)源事務(wù)一致性問題解決

    Atomikos + MybatisPlus解決多數(shù)據(jù)源事務(wù)一致性問題解決

    在實際項目的開發(fā)過程中,我們經(jīng)常會遇到在同一個項目或微服務(wù)中牽涉到使用兩個或多個數(shù)據(jù)源的,本文主要介紹了Atomikos + MybatisPlus解決多數(shù)據(jù)源事務(wù)一致性問題解決,具有一定的參考價值,感興趣的可以了解一下
    2024-07-07
  • 詳解JAVA 常量池

    詳解JAVA 常量池

    這篇文章主要介紹了JAVA 常量池的相關(guān)資料,文中講解非常詳細,示例代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • Java?spring?MVC環(huán)境中實現(xiàn)WebSocket的示例代碼

    Java?spring?MVC環(huán)境中實現(xiàn)WebSocket的示例代碼

    這篇文章主要介紹了Java?spring?MVC環(huán)境中實現(xiàn)WebSocket,本文通過示例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09
  • Spring?MVC基于注解的使用之JSON數(shù)據(jù)處理的方法

    Spring?MVC基于注解的使用之JSON數(shù)據(jù)處理的方法

    這篇文章主要介紹了Spring?MVC基于注解的使用JSON數(shù)據(jù)處理,json是一種輕量級的數(shù)據(jù)交換格式,是一種理想的數(shù)據(jù)交互語言,它易于閱讀和編寫,同時也易于機器解析和生成,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-05-05
  • Java按值傳遞和按址傳遞(面試常見)

    Java按值傳遞和按址傳遞(面試常見)

    這篇文章主要介紹了Java按值傳遞和按址傳遞(面試常見)知識,在面試筆試題中經(jīng)常會遇到,今天小編給大家詳細介紹下,需要的朋友可以參考下
    2017-02-02
  • 詳解Spring加載Properties配置文件的四種方式

    詳解Spring加載Properties配置文件的四種方式

    這篇文章主要介紹了詳解Spring加載Properties配置文件的四種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05
  • 創(chuàng)建網(wǎng)關(guān)項目(Spring Cloud Gateway)過程詳解

    創(chuàng)建網(wǎng)關(guān)項目(Spring Cloud Gateway)過程詳解

    這篇文章主要介紹了創(chuàng)建網(wǎng)關(guān)項目(Spring Cloud Gateway)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • 詳解在java中進行日期時間比較的4種方法

    詳解在java中進行日期時間比較的4種方法

    這篇文章主要介紹了詳解在java中進行日期時間比較的4種方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java ThreadLocal的使用詳解

    Java ThreadLocal的使用詳解

    ThreadLocal是線程私有的局部變量存儲容器,可以理解成每個線程都有自己專屬的存儲容器,用來存儲線程私有變量。ThreadLocal 在日常開發(fā)框架中應(yīng)用廣泛,但用不好也會出現(xiàn)各種問題,本文就此講解一下。
    2021-05-05
  • Java單鏈表反轉(zhuǎn)圖文教程

    Java單鏈表反轉(zhuǎn)圖文教程

    這篇文章主要給大家介紹了關(guān)于Java單鏈表反轉(zhuǎn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04

最新評論

云龙县| 江川县| 阜平县| 镇康县| 崇义县| 广东省| 梅州市| 全州县| 茌平县| 客服| 芜湖市| 崇左市| 德安县| 荣成市| 上犹县| 南江县| 新建县| 紫阳县| 安吉县| 黎平县| 利川市| 郸城县| 盐亭县| 出国| 高安市| 通榆县| 象山县| 洛川县| 北宁市| 商洛市| 田阳县| 南木林县| 内丘县| 江口县| 绥中县| 四会市| 白城市| 广河县| 竹溪县| 旬阳县| 保德县|