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

Java進階之SPI機制詳解

 更新時間:2021年05月17日 11:46:46   作者:聽到微笑  
Java SPI機制在很多大型中間建碼,例如Dubbo中均有采用,屬于高級Java開發(fā)的進階必備知識點,務(wù)必要求掌握.文中有非常詳細(xì)的代碼示例及解釋,需要的朋友可以參考下

一、前言

SPI的英文全稱為Service Provider Interface,字面意思為服務(wù)提供者接口,它是jdk提供給“服務(wù)提供廠商”或者“插件開發(fā)者”使用的接口。

在面向?qū)ο蟮脑O(shè)計中,模塊之間我們一般會采取面向接口編程的方式,而在實際編程過程過程中,API的實現(xiàn)是封裝在jar中,當(dāng)我們想要換一種實現(xiàn)方法時,還要生成新的jar替換以前的實現(xiàn)類。而通過jdk的SPI機制就可以實現(xiàn),首先不需要修改原來作為接口的jar的情況下,將原來實現(xiàn)的那個jar替換為另外一種實現(xiàn)的jar即可。

總結(jié)一下SPI的思想:在系統(tǒng)的各個模塊中,往往有不同的實現(xiàn)方案,例如日志模塊的方案、xml解析的方案等,為了在裝載模塊的時候不具體指明實現(xiàn)類,我們需要一種服務(wù)發(fā)現(xiàn)機制,java spi就提供這樣一種機制。有點類似于IoC的思想,將服務(wù)裝配的控制權(quán)移到程序之外,在模塊化設(shè)計時尤其重要。

順便提一下,Java SPI機制在很多大型中間件嗎,例如Dubbo中均有采用,屬于高級Java開發(fā)的進階必備知識點,務(wù)必要求掌握。

二、SPI規(guī)范

定義服務(wù)的通用接口,針對通用的服務(wù)接口,提供具體的實現(xiàn)類。

1.在jar包(服務(wù)提供者)的META-INF/services/目錄中,新建一個文件,文件名為SPI接口的"全限定名"。 文件內(nèi)容為該接口的具體實現(xiàn)類的"全限定名"

2.將spi所在jar放在主程序的classpath中

3.服務(wù)調(diào)用方使用java.util.ServiceLoader去動態(tài)加載具體的實現(xiàn)類到JVM中

三、SPI應(yīng)用案例

3.1 數(shù)據(jù)庫驅(qū)動

java.sql.Driver的spi實現(xiàn),有mysql驅(qū)動、oracle驅(qū)動等。以mysql為例,實現(xiàn)類是com.mysql.jdbc.Driver,在mysql-connector-java-5.1.6.jar中,我們可以看到有一個META-INF/services目錄,目錄下有一個文件名為java.sql.Driver的文件,其中的內(nèi)容是com.mysql.jdbc.Driver。

在我們使用JDBC獲取連接時,我們通常會調(diào)用DriverManager.getConnection()方法獲取連接對象,而在Driver類初始化時會使用ServiceLoader動態(tài)獲取classpath下“注冊”的驅(qū)動實現(xiàn):

static {
        loadInitialDrivers();
        println("JDBC DriverManager initialized");
}

private static void loadInitialDrivers() {
        .....
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
				//使用ServiceLoader動態(tài)加載具體的驅(qū)動實現(xiàn)類
                ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
                Iterator<Driver> driversIterator = loadedDrivers.iterator();
                try{
                    while(driversIterator.hasNext()) {
                        driversIterator.next();
                    }
                } catch(Throwable t) {
                // Do nothing
                }
                return null;
            }
        });
		.....
    }

3.2 Slf4j

slf4j是一個典型的門面接口,早起我們使用log4j作為日記記錄框架,我們需要同時引入slf4j和log4j的依賴。后面比較流行l(wèi)ogback,我們也想要把項目切換到logback上來,此時利用SPI的機制,我們只需要把log4j的jar包替換為logback的jar包就可以了。

log4j-to-slf4j.jar中我們可以看到前面提到的服務(wù)提供方的SPI接口聲明

這樣我們只需要將log4j-to-slf4j.jar引入classpath,slf4j就能夠獲取到org.apache.logging.slf4j.SLF4JProvider作為實現(xiàn)類。

四、SPI示例

模塊依賴關(guān)系:

4.1 spi-operate-service模塊

spi-operate-service中定義INumOperate接口:

package cn.bigcoder.spi.operate.service;

/**
 * @author: Jindong.Tian
 * @date: 2020-11-29
 * @description:
 **/
public interface INumOperate {

    int exec(int num1, int num2);
}

4.2 spi-operate-add模塊

spi-operate-add中定義加法實現(xiàn):

package cn.bigcoder.spi.operate.add;


import cn.bigcoder.spi.operate.service.INumOperate;

/**
 * @author: Jindong.Tian
 * @date: 2020-11-29
 * @description:
 **/
public class NumAddOperateImpl implements INumOperate {

    public int exec(int num1, int num2) {
        return num1 + num2;
    }
}

resource/METAINF/resoures目錄下創(chuàng)建cn.bigcoder.spi.operate.service.INumOperate文件:

cn.bigcoder.spi.operate.add.NumAddOperateImpl

4.3 spi-operate-multiplication模塊

spi-operate-multiplication模塊中定義乘法的實現(xiàn):

package cn.bigcoder.spi.operate.multiplication;

import cn.bigcoder.spi.operate.service.INumOperate;

/**
 * @author: Jindong.Tian
 * @date: 2020-11-29
 * @description:
 **/
public class NumMultiOperateImpl implements INumOperate {
    
    public int exec(int num1, int num2) {
        return num1 * num2;
    }
}

同樣的在resource/METAINF/resoures目錄下創(chuàng)建cn.bigcoder.spi.operate.service.INumOperate文件:

cn.bigcoder.spi.operate.multiplication.NumMultiOperateImpl

4.4 spi-operate-consumer模塊

spi-operate-consumer模塊中,我們編寫測試類獲取classpath中INumOperate實現(xiàn)類:

package cn.bigcoder.spi.operate;

import cn.bigcoder.spi.operate.service.INumOperate;
import org.junit.Test;

import java.util.Iterator;
import java.util.ServiceLoader;

/**
 * @author: Jindong.Tian
 * @date: 2020-11-29
 * @description:
 **/
public class INumOperateTest {
    @Test
    public void test() {
        // SPI機制,尋找所有的實現(xiàn)類,順序執(zhí)行
        ServiceLoader<INumOperate> loader = ServiceLoader.load(INumOperate.class);
        Iterator<INumOperate> iterator = loader.iterator();
        if (iterator.hasNext()) {
            INumOperate numOperate = iterator.next();
            System.out.println(numOperate.exec(1, 2));
        } else {
            throw new RuntimeException("classpath中未找到cn.bigcoder.spi.operate.INumOperate實現(xiàn)類");
        }
    }
}

此時如果我們在spi-operate-consumer中引入spi-operate-add,則測試方法執(zhí)行求和操作;如果引入spi-operate-multiplication,則測試方法執(zhí)行乘法操作。

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

相關(guān)文章

  • SpringBoot通知機制的實現(xiàn)方式

    SpringBoot通知機制的實現(xiàn)方式

    這篇文章主要介紹了SpringBoot通知機制的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java swing框架實現(xiàn)貪吃蛇游戲

    java swing框架實現(xiàn)貪吃蛇游戲

    這篇文章主要為大家詳細(xì)介紹了java swing框架實現(xiàn)貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-12-12
  • 使用jpa的時候set實體類屬性自動持久化的解決方案

    使用jpa的時候set實體類屬性自動持久化的解決方案

    這篇文章主要介紹了使用jpa的時候set實體類屬性自動持久化的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • AbstractQueuedSynchronizer(AQS)鎖狀態(tài)同步和排隊管理

    AbstractQueuedSynchronizer(AQS)鎖狀態(tài)同步和排隊管理

    這篇文章主要介紹了為大家AbstractQueuedSynchronizer(AQS)鎖狀態(tài)同步和排隊管理源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • java實現(xiàn)簡單的爬蟲之今日頭條

    java實現(xiàn)簡單的爬蟲之今日頭條

    最近在學(xué)習(xí)搜索方面的東西,需要了解網(wǎng)絡(luò)爬蟲方面的知識,雖然有很多開源的強大的爬蟲,但本著學(xué)習(xí)的態(tài)度,想到之前在做資訊站的時候需要用到爬蟲來獲取一些文章,今天剛好有空就研究了一下.在網(wǎng)上看到了一個demo,使用的是Jsoup,我拿過來修改了一下,有需要的朋友可以參考
    2016-11-11
  • Flowable歷史查詢實例分析

    Flowable歷史查詢實例分析

    這篇文章主要介紹了Flowable歷史查詢實例分析,歷史是記錄流程執(zhí)行過程中發(fā)生的事情,并將其永久存儲的組件,與運行時數(shù)據(jù)不同,歷史數(shù)據(jù)在流程實例完成以后仍保存在數(shù)據(jù)庫中,下面我們來深入了解
    2023-10-10
  • Java多線程的具體介紹與使用筆記小結(jié)

    Java多線程的具體介紹與使用筆記小結(jié)

    Java多線程詳細(xì)介紹線程是程序執(zhí)行的最小單元,多線程是指程序同一時間可以有多個執(zhí)行單元運行(這個與你的CPU核心有關(guān))。 接下來通過本文給大家介紹Java多線程的具體介紹與使用筆記小結(jié),感興趣的朋友一起看看吧
    2021-05-05
  • Spring Aware標(biāo)記接口使用案例解析

    Spring Aware標(biāo)記接口使用案例解析

    這篇文章主要介紹了Spring Aware標(biāo)記接口使用案例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • 解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個文件無法傳輸多個問題

    解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個文件無法傳輸多個問題

    這篇文章主要介紹了解決DataInputStream?read不等于-1,socket文件傳輸只能傳輸一個文件無法傳輸多個問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Mybatis-plus自動填充不生效或自動填充數(shù)據(jù)為null原因及解決方案

    Mybatis-plus自動填充不生效或自動填充數(shù)據(jù)為null原因及解決方案

    本文主要介紹了Mybatis-plus自動填充不生效或自動填充數(shù)據(jù)為null原因及解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05

最新評論

元谋县| 汪清县| 韶山市| 光泽县| 昆明市| 长海县| 象州县| 新蔡县| 增城市| 凯里市| 筠连县| 奉节县| 恩平市| 襄樊市| 舒城县| 义乌市| 福鼎市| 五常市| 泉州市| 安丘市| 阿拉善盟| 邹平县| 将乐县| 五台县| 荃湾区| 阳山县| 濮阳县| 迁西县| 玉门市| 永胜县| 四川省| 瓦房店市| 中宁县| 黄平县| 锡林郭勒盟| 留坝县| 会同县| 古浪县| 梧州市| 宕昌县| 南汇区|