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

一文搞懂Java的SPI機制(推薦)

 更新時間:2021年11月23日 10:52:41   作者:JavaEdge.  
Java定義了一套JDBC的接口,但并未提供具體實現(xiàn)類,而是在不同云廠商提供的數(shù)據(jù)庫實現(xiàn)包。這篇文章給大家介紹Java的SPI機制,感興趣的朋友一起看看吧

1 簡介

SPI,Service Provider Interface,一種服務發(fā)現(xiàn)機制。


有了SPI,即可實現(xiàn)服務接口與服務實現(xiàn)的解耦:

  • 服務提供者(如 springboot starter)提供出 SPI 接口。身為服務提供者,在你無法形成絕對規(guī)范強制時,適度"放權(quán)" 比較明智,適當讓客戶端去自定義實現(xiàn)
  • 客戶端(普通的 springboot 項目)即可通過本地注冊的形式,將實現(xiàn)類注冊到服務端,輕松實現(xiàn)可插拔

缺點

  • 不能按需加載。
  • 雖然 ServiceLoader 做了延遲加載,但是只能通過遍歷的方式全部獲取。如果其中某些實現(xiàn)類很耗時,而且你也不需要加載它,那么就形成了資源浪費獲取某個實現(xiàn)類的方式不夠靈活,只能通過迭代器的形式獲取

Dubbo SPI 實現(xiàn)方式對以上兩點進行了業(yè)務優(yōu)化。

源碼

應用程序通過迭代器接口獲取對象實例,這里首先會判斷 providers 對象中是否有實例對象:

  • 有實例,那么就返回
  • 沒有,執(zhí)行類的裝載步驟,具體類裝載實現(xiàn)如下:

LazyIterator#hasNextService 讀取 META-INF/services 下的配置文件,獲得所有能被實例化的類的名稱,并完成 SPI 配置文件的解析

LazyIterator#nextService 負責實例化 hasNextService() 讀到的實現(xiàn)類,并將實例化后的對象存放到 providers 集合中緩存

使用

如某接口有3個實現(xiàn)類,那系統(tǒng)運行時,該接口到底選擇哪個實現(xiàn)類呢?
這時就需要SPI,根據(jù)指定或默認配置,找到對應實現(xiàn)類,加載進來,然后使用該實現(xiàn)類實例。

如下系統(tǒng)運行時,加載配置,用實現(xiàn)A2實例化一個對象來提供服務:

再如,你要通過jar包給某個接口提供實現(xiàn),就在自己jar包的META-INF/services/目錄下放一個接口同名文件,指定接口的實現(xiàn)是自己這個jar包里的某類即可:

別人用這個接口,然后用你的jar包,就會在運行時通過你的jar包指定文件找到這個接口該用哪個實現(xiàn)類。這是JDK內(nèi)置提供的功能。

我就不定義在 META-INF/services 下面行不行?就想定義在別的地方可以嗎?

No!JDK 已經(jīng)規(guī)定好配置路徑,你若隨便定義,類加載器可就不知道去哪里加載了

假設你有個工程P,有個接口A,A在P無實現(xiàn)類,系統(tǒng)運行時怎么給A選實現(xiàn)類呢?
可以自己搞個jar包,META-INF/services/,放上一個文件,文件名即接口名,接口A的實現(xiàn)類=com.javaedge.service.實現(xiàn)類A2。
讓P來依賴你的jar包,等系統(tǒng)運行時,P跑起來了,對于接口A,就會掃描依賴的jar包,看看有沒有META-INF/services文件夾:

有,再看看有無名為接口A的文件: 有,在里面查找指定的接口A的實現(xiàn)是你的jar包里的哪個類即可

適用場景

插件擴展

比如你開發(fā)了一個開源框架,若你想讓別人自己寫個插件,安排到你的開源框架里中,擴展功能時。

如JDBC。Java定義了一套JDBC的接口,但并未提供具體實現(xiàn)類,而是在不同云廠商提供的數(shù)據(jù)庫實現(xiàn)包。

但項目運行時,要使用JDBC接口的哪些實現(xiàn)類呢?

一般要根據(jù)自己使用的數(shù)據(jù)庫驅(qū)動jar包,比如我們最常用的MySQL,其mysql-jdbc-connector.jar 里面就有:

系統(tǒng)運行時碰到你使用JDBC的接口,就會在底層使用你引入的那個jar中提供的實現(xiàn)類。

案例

如sharding-jdbc 數(shù)據(jù)加密模塊,本身支持 AES 和 MD5 兩種加密方式。但若客戶端不想用內(nèi)置的兩種加密,偏偏想用 RSA 算法呢?難道每加一種算法,sharding-jdbc 就要發(fā)個版本?

sharding-jdbc 可不會這么蠢,首先提供出 EncryptAlgorithm 加密算法接口,并引入 SPI 機制,做到服務接口與服務實現(xiàn)分離的效果。
客戶端想要使用自定義加密算法,只需在客戶端項目 META-INF/services 的路徑下定義接口的全限定名稱文件,并在文件內(nèi)寫上加密實現(xiàn)類的全限定名


這就顯示了SPI的優(yōu)點:

  • 客戶端(自己的項目)提供了服務端(sharding-jdbc)的接口自定義實現(xiàn),但是與服務端狀態(tài)分離,只有在客戶端提供了自定義接口實現(xiàn)時才會加載,其它并沒有關(guān)聯(lián);客戶端的新增或刪除實現(xiàn)類不會影響服務端
  • 如果客戶端不想要 RSA 算法,又想要使用內(nèi)置的 AES 算法,那么可以隨時刪掉實現(xiàn)類,可擴展性強,插件化架構(gòu)

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

相關(guān)文章

  • springboot如何解決非controller類引用service的問題

    springboot如何解決非controller類引用service的問題

    這篇文章主要介紹了springboot如何解決非controller類引用service的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • RabbitMQ消息拒絕如何解決

    RabbitMQ消息拒絕如何解決

    這篇文章主要介紹了RabbitMQ消息拒絕如何解決問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • SpringBoot在項目停止(服務停止/關(guān)閉退出)之后執(zhí)行的方法

    SpringBoot在項目停止(服務停止/關(guān)閉退出)之后執(zhí)行的方法

    這篇文章主要給大家介紹了SpringBoot在項目停止(服務停止/關(guān)閉退出)之后執(zhí)行的兩種方法,實現(xiàn)DisposableBean接口和使用@PreDestroy注解,文中有詳細的代碼講解,具有一定的參考價值,需要的朋友可以參考下
    2023-12-12
  • maven-surefire-plugin總結(jié)示例詳解

    maven-surefire-plugin總結(jié)示例詳解

    這篇文章主要介紹了maven-surefire-plugin總結(jié),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • java多線程之線程安全的單例模式

    java多線程之線程安全的單例模式

    這篇文章主要為大家詳細介紹了java多線程之線程安全的單例模式,文章內(nèi)容全面,感興趣的小伙伴們可以參考一下
    2016-03-03
  • SSM框架把日志信息保存到數(shù)據(jù)庫過程詳解

    SSM框架把日志信息保存到數(shù)據(jù)庫過程詳解

    這篇文章主要介紹了SSM框架把日志信息保存到數(shù)據(jù)庫過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-07-07
  • mybatis @Intercepts的用法解讀

    mybatis @Intercepts的用法解讀

    這篇文章主要介紹了mybatis @Intercepts的用法解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • JAVA實現(xiàn)長連接(含心跳檢測Demo)

    JAVA實現(xiàn)長連接(含心跳檢測Demo)

    這篇文章主要介紹了JAVA實現(xiàn)長連接(含心跳檢測Demo),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-10-10
  • java根據(jù)當前時間獲取yyyy-MM-dd?HH:mm:ss標準格式的時間代碼示例

    java根據(jù)當前時間獲取yyyy-MM-dd?HH:mm:ss標準格式的時間代碼示例

    在Java中可以使用java.time包中的LocalDateTime類和DateTimeFormatter類來獲取并格式化當前時間為yyyy-MM-dd?HH:mm:ss的格式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • jar包手動添加到本地maven倉庫的步驟詳解

    jar包手動添加到本地maven倉庫的步驟詳解

    在寫程序的過程中,有時候會遇到私服里沒有需要的jar包的情況,這時候我們就可以手動導入jar包到本地倉庫進行使用,下面這篇文章主要給大家介紹了關(guān)于jar包手動添加到本地maven倉庫的相關(guān)資料,需要的朋友可以參考下
    2022-08-08

最新評論

广安市| 阳信县| 稷山县| 丰原市| 黄冈市| 呼和浩特市| 万山特区| 罗城| 海阳市| 五莲县| 荣成市| 陆河县| 拜城县| 龙州县| 瑞昌市| 海伦市| 咸丰县| 油尖旺区| 潞西市| 祁东县| 灵璧县| 东乌| 嘉峪关市| 吉首市| 兰西县| 巴中市| 隆德县| 苏尼特左旗| 栖霞市| 潼关县| 平凉市| 天长市| 纳雍县| 苍溪县| 清镇市| 玉田县| 海丰县| 大新县| 漳浦县| 滨海县| 鲁山县|