日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

作者 | 京東云開發(fā)者-京東物流 龔航林

原文鏈接:https://my.oschina.NET/u/4090830/blog/10116011

1 SPI 簡(jiǎn)介1.1 SPI(Service Provider Interface)

本質(zhì):將接口實(shí)現(xiàn)類的全限定名配置在文件中,并由服務(wù)加載器讀取配置文件,加載實(shí)現(xiàn)類。這樣可以在運(yùn)行時(shí),動(dòng)態(tài)為接口替換實(shí)現(xiàn)類。

JAVA SPI:用來設(shè)計(jì)給服務(wù)提供商做插件使用的。基于策略模式來實(shí)現(xiàn)動(dòng)態(tài)加載的機(jī)制。我們?cè)诔绦蛑欢x一個(gè)接口,具體的實(shí)現(xiàn)交個(gè)不同的服務(wù)提供者;在程序啟動(dòng)的時(shí)候,讀取配置文件,由配置確定要調(diào)用哪一個(gè)實(shí)現(xiàn)。

dubbo SPI:在 dubbo 中也有 SPI 機(jī)制,雖然都需要將接口全限定名配置在文件中,但是 dubbo 并沒有使用 java 的 spi 機(jī)制,而是重新實(shí)現(xiàn)了一套功能更強(qiáng)的 SPI 機(jī)制,支持了 AOP 與依賴注入,并且 利用緩存提高加載實(shí)現(xiàn)類的性能,同時(shí) 支持實(shí)現(xiàn)類的靈活獲取。基于 SPI,我們可以很容易的對(duì) Dubbo 進(jìn)行拓展。例如 dubbo 當(dāng)中的 protocol,LoadBalance 等都是通過 SPI 機(jī)制擴(kuò)展。

2 java SPI2.1 實(shí)現(xiàn)過程

1)需要在 classpath 下創(chuàng)建一個(gè)目錄,該目錄命名必須是:META-INF/service

2)在該目錄下創(chuàng)建一個(gè) 文本文件,該文件需要滿足以下幾個(gè)條件

  • 文件名必須是擴(kuò)展的接口的全路徑名稱
  • 文件內(nèi)部描述的是該擴(kuò)展接口的所有實(shí)現(xiàn)類
  • 文件的編碼格式是 UTF-8

3)通過 java.util.ServiceLoader 的加載機(jī)制來加載服務(wù)

深入理解java和dubbo的SPI機(jī)制

深入理解java和dubbo的SPI機(jī)制

2.2 工作原理

1)當(dāng)調(diào)用 ServiceLoader.load (Class clz) 方法時(shí),會(huì)到 jar 中中的目錄 “META-INF/services/“ + clz.getName 進(jìn)行文件讀取,

2)當(dāng)在調(diào)用 ServiceLoader.forEach 方法時(shí),實(shí)際走的是 LazyIterator,當(dāng)在調(diào)用 LazyIterator.hasNext 時(shí),在文件中讀取到實(shí)際的服務(wù)實(shí)現(xiàn)類并把它們通過調(diào)用 Class.forName (String name, boolean initialize,ClassLoader loader)。

深入理解java和dubbo的SPI機(jī)制

2.3 實(shí)際應(yīng)用

javaSPI 我們最熟悉的應(yīng)用就是數(shù)據(jù)庫(kù)驅(qū)動(dòng)了,MySQL 和 oracle 驅(qū)動(dòng)針對(duì) JDBC 分別有自己的實(shí)現(xiàn),這就有賴于 java 的 SPI 機(jī)制。

深入理解java和dubbo的SPI機(jī)制

3 dubbo SPI3.1 實(shí)現(xiàn)過程

1)需要在 classpath 下創(chuàng)建一個(gè)目錄,該目錄命名可以是:META-INF/service/、META-INF/dubbo/、META-INF/dubbo/internal/

2)在該目錄下創(chuàng)建一個(gè) 文本文件,該文件需要滿足以下幾個(gè)條件

  • 文件名必須是擴(kuò)展的接口的全路徑名稱
  • 文件內(nèi)部描述的是該擴(kuò)展接口的所有實(shí)現(xiàn)類,將服務(wù)實(shí)現(xiàn)類寫成 KV 鍵值對(duì)的形式,Key 是拓展類的 name,Value 是擴(kuò)展的全限定名實(shí)現(xiàn)類。

3)通過 org.Apache.dubbo.common.extension.Extensier 的加載機(jī)制來加載服務(wù)

深入理解java和dubbo的SPI機(jī)制

深入理解java和dubbo的SPI機(jī)制

3.2 工作原理

1)我們首先通過 Extensier 的 getExtensier 方法獲取一個(gè)接口的 Extensier 實(shí)例,然后再通過 Extensier 的 getExtension 方法獲取拓展類對(duì)象,源碼如下,首先是 getExtensier 方法:

深入理解java和dubbo的SPI機(jī)制

new Extensier (type) 源碼如下:

注意這里創(chuàng)建 Extensier 對(duì)象的構(gòu)造方法如下:Extensier.getExtensier 獲取 ExtensionFactory 接口的拓展類,再通過 getAdaptiveExtension 從拓展類中獲取目標(biāo)拓展類。

2)通過 Extensier.getExtensier 取到接口的加載器 Loader 之后,再通過 getExtension 方法獲取需要拓展類對(duì)象。

深入理解java和dubbo的SPI機(jī)制

以上代碼首先檢查 holder 中的實(shí)例緩存,緩存未命中則創(chuàng)建拓展對(duì)象。dubbo 中包含了大量的擴(kuò)展點(diǎn)緩存。這個(gè)就是典型的使用空間換時(shí)間的做法。

深入理解java和dubbo的SPI機(jī)制

創(chuàng)建拓展類對(duì)象步驟分別為:

  1. 通過 getExtensionClasses 從配置文件中加載所有的拓展類,再通過名稱獲取目標(biāo)拓展類
  2. 通過反射創(chuàng)建拓展對(duì)象
  3. 向拓展對(duì)象中注入依賴
  4. 將拓展對(duì)象包裹在相應(yīng)的 WrApper 對(duì)象中

我們接下來重點(diǎn)看下 getExtensionClasses 方法:

深入理解java和dubbo的SPI機(jī)制

先從緩存中獲取 class,緩存未命中則調(diào)用 loadExtensionClasses 方法加載,我們?cè)倏聪?loadExtensionClasses 這個(gè)方法:

我們看到這里遍歷調(diào)用了多個(gè)策略去加載 class 的,跟到這里我們發(fā)現(xiàn)非常有意思的是:dubbo 在加載 META-INF 目錄下的 class 鍵值對(duì)的時(shí)候采用了 javaSPI 的方式

深入理解java和dubbo的SPI機(jī)制

深入理解java和dubbo的SPI機(jī)制

這里 dubbo 使用 javaSPI 的方式加載到 3 中類加載策略:

org.apache.dubbo.common.extension.DubboInternalLoadingStrategy 用于加載 META-INF/dubbo/internal/ 中的 class

org.apache.dubbo.common.extension.DubboLoadingStrategy 用于加載 META-INF/dubbo/ 中的 class

org.apache.dubbo.common.extension.ServicesLoadingStrategy 用于加載 META-INF/service/ 中的 class

dubbo 的 SPI 還提供了自適應(yīng)(Adaptive)、自動(dòng)注入的功能就不在這里過多展開了,有興趣可以自行了解。

3.3 實(shí)際應(yīng)用

dubbo 中大量使用了 SPI 機(jī)制:

深入理解java和dubbo的SPI機(jī)制

例如 dubbo 的多協(xié)議的實(shí)現(xiàn):

深入理解java和dubbo的SPI機(jī)制

4 javaSPI 和 dubboSPI 對(duì)比

  1. Java SPI 在加載擴(kuò)展點(diǎn)的時(shí)候,會(huì)一次性加載所有可用的擴(kuò)展點(diǎn),很多是不需要的,會(huì)浪費(fèi)系統(tǒng)資源。dubboSPI 有選擇性地加載所需要的 SPI 接口。
  2. javaSPI 配置文件中只是簡(jiǎn)單的列出了所有的擴(kuò)展實(shí)現(xiàn),而沒有給他們命名。導(dǎo)致在程序中很難去準(zhǔn)確的引用它們。而 dubboSPI 配置文件中以鍵值對(duì)的形式有別名,易于區(qū)分。
  3. SPI 擴(kuò)展如果依賴其他的擴(kuò)展,javaspi 做不到自動(dòng)注入和裝配,dubbo 可以實(shí)現(xiàn)自動(dòng)注入。
  4. javaSPI 不提供類似于 Spring 的 IOC 和 AOP 功能,dubboSPI 是支持的

分享到:
標(biāo)簽:java
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定