欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文搞懂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ī)范強制時,適度"放權" 比較明智,適當讓客戶端去自定義實現(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ù)庫驅動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)時才會加載,其它并沒有關聯(lián);客戶端的新增或刪除實現(xiàn)類不會影響服務端
  • 如果客戶端不想要 RSA 算法,又想要使用內(nèi)置的 AES 算法,那么可以隨時刪掉實現(xiàn)類,可擴展性強,插件化架構

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

相關文章

  • RabbitMQ的消息確認機制的詳細總結

    RabbitMQ的消息確認機制的詳細總結

    RabbitMQ消息確認機制指的是在消息傳遞過程中,發(fā)送方發(fā)送消息后,接收方需要對消息進行確認,以確保消息被正確地接收和處理,本文就講給大家詳解介紹RabbitMQ的幾種消息確認機制,需要的朋友可以參考下
    2023-07-07
  • 將java中的 string 類型轉成 數(shù)組案例

    將java中的 string 類型轉成 數(shù)組案例

    這篇文章主要介紹了將java中的 string 類型轉成 數(shù)組案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • 引入SpringCloud-gateway報錯的解決方案

    引入SpringCloud-gateway報錯的解決方案

    這篇文章主要介紹了引入SpringCloud-gateway報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • EasyCode整合mybatis-plus的配置詳解

    EasyCode整合mybatis-plus的配置詳解

    本文主要介紹了EasyCode整合mybatis-plus的配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-09-09
  • 分享Java死鎖的4種排查工具

    分享Java死鎖的4種排查工具

    這篇文章主要介紹了分享Java死鎖的4種排查工具,死鎖指的是兩個或兩個以上的運算單元,都在等待對方停止執(zhí)行,以取得系統(tǒng)資源,但是沒有一方提前退出,就稱為死鎖,下文更多相關內(nèi)容需要的小伙伴可以參考一下
    2022-05-05
  • Java實現(xiàn)TCP和UDP協(xié)議詳解

    Java實現(xiàn)TCP和UDP協(xié)議詳解

    這篇文章主要介紹了Java實現(xiàn)TCP和UDP協(xié)議詳解,TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報協(xié)議)是兩種最常用的傳輸層協(xié)議,它們都用于在網(wǎng)絡上傳輸數(shù)據(jù),但是它們之間有很多不同之處,需要的朋友可以參考下
    2023-07-07
  • Spring Cloud 系列之服務調(diào)用 OpenFeign的實現(xiàn)

    Spring Cloud 系列之服務調(diào)用 OpenFeign的實現(xiàn)

    這篇文章主要介紹了Spring Cloud 系列之服務調(diào)用 OpenFeign的實現(xiàn),需要的朋友可以參考下
    2020-11-11
  • Java中Object.equals和String.equals的區(qū)別詳解

    Java中Object.equals和String.equals的區(qū)別詳解

    這篇文章主要給大家介紹了Java中Object.equals和String.equals的區(qū)別,文中通過一個小示例讓大家輕松的明白這兩者的區(qū)別,對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-04-04
  • java后臺批量下載文件并壓縮成zip下載的方法

    java后臺批量下載文件并壓縮成zip下載的方法

    這篇文章主要為大家詳細介紹了java后臺批量下載文件并壓縮成zip下載的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • Log4j 配置日志打印時區(qū)的實現(xiàn)方法

    Log4j 配置日志打印時區(qū)的實現(xiàn)方法

    下面小編就為大家分享一篇Log4j 配置日志打印時區(qū)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12

最新評論