中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Dubbo怎么實現擴展機制

發布時間:2021-12-15 16:18:55 來源:億速云 閱讀:153 作者:iii 欄目:云計算

這篇文章主要介紹“Dubbo怎么實現擴展機制”,在日常操作中,相信很多人在Dubbo怎么實現擴展機制問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Dubbo怎么實現擴展機制”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

SPI

Dubbo 就是利用 SPI (Service Provider Interface)來實現擴展機制的。

這個 SPI 想必你們都很熟悉,在大學寫數據庫大作業的時候就碰到了,訪問數據庫需要用到 java.sql.Driver

市面上的數據庫五花八門,每個數據庫廠商都有自己的實現,所以肯定需要定制一個接口,這樣我們面向接口編程即可。

而具體的實現則可以通過配置來加載,JDK SPI 這時候就派上用場了。

其實一點都不神奇,就是約定一個地方,加載的時候就去那個地方找實現類。

Dubbo怎么實現擴展機制

約定一個地方直白點說就是代碼里面寫死了一個目錄,這個目錄就是 META-INF/services/

然后在這個目錄下創建一個文件,用接口全限定名來命名,文件內容就是實現類的全限定名。

Dubbo怎么實現擴展機制

到時候要實現類就根據接口名來這里找,然后實例化就行了。

挺簡單的吧,這就是 JDK SPI,但是它不滿足 Dubbo 的需求。

因為 Dubbo 把自身的一些實現也剝離出來成為擴展,而這些實現還是有點多的,也不需要全部用上。

如果用 JDK SPI 會把配置文件里面的類全部加載,這就導致資源的浪費。用的時候還需要遍歷過去才能找到對應的實現。

所以 Dubbo 就在 JDK SPI 的基礎上實現了個 Dubbo 的 SPI,可以根據指定的名稱按需加載實現類,比如拿 Cluster 來說就有這么多實現類。

Dubbo怎么實現擴展機制

約定的地方改了一下,一共有三個目錄。

  • META-INF/dubbo/internal/ :這里是存放 Dubbo 內部使用的 SPI 配置文件。

  • META-INF/dubbo/ :這里是存放用戶自定義 SPI 配置文件。

  • META-INF/services/:兼容 JDK SPI

然后文件里面的內容是key=value形式,這樣就可以根據 key 找到對應的實現類。

然后在注解上可以配置默認的 key 來選擇默認的實現類,比如 Cluster 默認的實現是 failover。

也可以通過 URL 參數來選擇實現類。

Dubbo怎么實現擴展機制

還有像 JDK SPI 擴展點加載失敗的話,連擴展點名稱都拿不到,到時候報錯也不知道哪里出問題。

而 Dubbo SPI 則不會吃了錯誤,并且還提供了擴展點的自動注入和 AOP 功能。

大致了解了 Dubbo  SPI 之后,我們再來深入看看實現細節。

Dubbo SPI 實現細節

Dubbo SPI 的核心實現在 ExtensionLoader 中,它負責擴展點的加載和生命周期的維護,類似 JDK SPI 的 ServiceLoader。

這里要先提一點看源碼的小技巧了。

開源框架都會有單元測試,而單元測試里面就會有我們看源碼時候想要的各種功能實現,我們就可以從單元測試入手得知一些功能的劃分,然后斷點調試逐漸深入。

比如今天文章的 ExtensionLoader ,它在 dubbo-common 模塊中,咱們就進入 test 來看看它測試用例怎么寫的。

Dubbo怎么實現擴展機制

當然除了通過文件夾來找,直接用文件名搜也行。

找到了就好辦了,數據都是造好的,找到你想要調試的方法,斷點一設,箭頭一點,這不就美滋滋了嗎?

Dubbo怎么實現擴展機制

好了,小技巧分享完畢,回到 ExtensionLoader,我們簡單點就用 Dubbo 單元測試的數據來看看實現。

有個叫 SimpleExt 的類,有三個實現,默認的實現是 impl1。

Dubbo怎么實現擴展機制

再來看看 SPI 配置文件的內容,可以看到為了測試還故意寫了一些空格在配置文件中。

Dubbo怎么實現擴展機制

然后現在如果要找 impl2 這個實現,通過以下代碼調用即可。

SimpleExt ext = ExtensionLoader     .getExtensionLoader(SimpleExt.class).getExtension("impl2")

一個擴展接口對應有個 ExtensionLoader,找到對應的 ExtensionLoader,然后再加載對應名字的實現類。

接下來會有源碼,不過沒關系,還是很簡單的,想要深入源碼這關必須過。

Dubbo怎么實現擴展機制

可以看到getExtensionLoader 是靜態的,里面邏輯也很簡單就是從緩存找接口對應的 ExtensionLoader,找不到就新建一個返回。

現在有了 ExtensionLoader,咱們再來看看 getExtension 的邏輯,來看看是如何通過擴展點 name 找到對應的實現類的。

Dubbo怎么實現擴展機制

可以看到又是有個緩存操作,邏輯非常簡單,先去緩存找實例,如果沒有則創建實例。

要說細節就是用到了雙檢鎖,然后用 holder 來保證可見性和防止指令重排。應該看到注釋上的 holder 構造了吧,volatile 和雙檢鎖的搭配,這里就不深入了。

我們來看看 createExtension,這是要創建擴展點了,代碼有點長,但是我都做了相應的注釋,包括綠色的注釋。

Dubbo怎么實現擴展機制

邏輯還是很簡單的,詳細的代碼沒有具體展示,我先口述一下。

  1. 通過接口類名去三個目錄找到對應的文件。

  2. 解析文件內容生成 class 對象,然后緩存到 cachedClasses 中。

  3. 然后通過 name 去 cachedClasses  中找到對應的 class 對象。

  4. 去緩存 EXTENSION_INSTANCES 看看是否已經實例化過了。

  5. 沒有的話就實例化,然后調用 injectExtension 實現自動注入。

  6. 再通過 cachedWrapperClasses 實現包裝,將最后的包裝類返回。

有幾點不清晰沒關系,咱們接著分析,腦海中先大概知道要做什么,然后再來看看具體是怎么做的。

源碼中的 loadDirectory 就是去目錄找文件,然后解析,最終會調用  loadClass,這個方法很關鍵,我們詳細分析一下,為了便于觀看,刪除了一些代碼。

Dubbo怎么實現擴展機制

自適應咱們先略過,只要知道是在這里記錄的即可。

然后上面提到的 AOP 相關的 cachedWrapperClasses 就是在這里記錄的,如果判斷它是包裝類呢?

Dubbo怎么實現擴展機制

簡單粗暴但是有效,只要有當前類作為構造器參數的類就是包裝類,有點拗口,多讀幾遍就理解了。

現在我們再回過頭來看看這段代碼,Dubbo 的 AOP。

Dubbo怎么實現擴展機制

把擴展類對應的包裝類都記錄下來放在  cachedWrapperClasses 中,然后在實例化擴展類的時候就一層一層的把擴展類包起來,最終返回的就是包裝類。

為什么說這就是 AOP 呢?因為等于把一些邏輯切進了擴展實現類中。

其實就是把擴展對象的公共邏輯移到包裝類中,我們看下單元測試的例子就很清晰了。

Dubbo怎么實現擴展機制

從圖中可以看到有兩個擴展實現類,兩個包裝類,具體邏輯就不看了,不是重點,配置文件如下:

Dubbo怎么實現擴展機制

然后再看一下單元測試的運行結果,可以看到最終返回的其實是 Ext5Wrapper1 對象,并且它還包著 wrapper2 對象。

Dubbo怎么實現擴展機制

所以 echo 方法的調用鏈就是:Ext5Wrapper1 ->Ext5Wrapper2->Ext5impl1

也就起到了 AOP 的效果。

接下來我們再來看看 injectExtension,是如何實現 Dubbo 的自動注入。

Dubbo怎么實現擴展機制

到此,關于“Dubbo怎么實現擴展機制”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

广西| 临沂市| 利辛县| 巴塘县| 巴里| 襄樊市| 孝昌县| 宜昌市| 滨海县| 正蓝旗| 东莞市| 七台河市| 嘉峪关市| 铁岭县| 剑川县| 永和县| 临颍县| 昭通市| 维西| 青冈县| 济南市| 若尔盖县| 阳原县| 镇赉县| 宜章县| 淮阳县| 桐庐县| 建德市| 青铜峡市| 小金县| 沈阳市| 广宗县| 普兰县| 龙海市| 邢台市| 元氏县| 揭阳市| 新泰市| 湾仔区| 武鸣县| 太和县|