Dubbo源碼分析之ExtensionLoader

參考:http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html

1.簡介

SPI 全稱爲 Service Provider Interface,是一種服務發現機制。SPI 的本質是將接口實現類的全限定名配置在文件中,並由服務加載器讀取配置文件,加載實現類。這樣可以在運行時,動態爲接口替換實現類。正因此特性,我們可以很容易的通過 SPI 機制爲我們的程序提供拓展功能。SPI 機制在第三方框架中也有所應用,比如 Dubbo 就是通過 SPI 機制加載所有的組件。不過,Dubbo 並未使用 Java 原生的 SPI 機制,而是對其進行了增強,使其能夠更好的滿足需求。在 Dubbo 中,SPI 是一個非常重要的模塊。基於 SPI,我們可以很容易的對 Dubbo 進行拓展。如果大家想要學習 Dubbo 的源碼,SPI 機制務必弄懂。接下來,我們先來了解一下 Java SPI 與 Dubbo SPI 的用法,然後再來分析 Dubbo SPI 的源碼。

需要特別說明的是,本篇文章的源碼版本爲 dubbo-4.0.0。因此大家在閱讀文章的過程中,需注意將代碼版本切換到 dubbo-4.0.0 tag 上。

dubbo的目錄結構如下,感興趣的可以自行到github上去下載到本地

本次記錄的ExtensionLoader用法是在如下目錄下。

首先咱們 先來看一下他的基本用法

找到dubbo的test

我們來隨便在測試類裏面寫個測試

@Test
public void testExt2() throws Exception {
    ExtensionLoader<Ext2> extensionLoader = ExtensionLoader.getExtensionLoader(Ext2.class);
    Ext2 impl1 = extensionLoader.getExtension("impl1");
    String value = impl1.echo(new UrlHolder(), "2");
    System.err.println(value);
    //==========================
    Ext2 impl2 = extensionLoader.getExtension("impl2");
    String value2 = impl2.echo(new UrlHolder(), "2");
    System.err.println(value2);
}

點擊Ext2類進去看見是一個接口

@SPI
public interface Ext2 {
    // one of the properties of an argument is an instance of URL.
    @Adaptive
    String echo(UrlHolder holder, String s);

    String bang(URL url, int i);
}

並且是加了@SPI和在方法上加了 @Adaptive註解的接口,這裏需要留意下。後面源碼分析時候會講到。

通過idea看見Ext2 有定義了三個實現類

三個實現類幾乎一樣,只是作爲區分而已

public class Ext2Impl2 implements Ext2 {
    public String echo(UrlHolder holder, String s) {
        return "Ext2Impl2-echo";
    }

    public String bang(URL url, int i) {
        return "bang2";
    }
}

接下來看一下三個實現類定義的文件

內容爲:

impl1=org.apache.dubbo.common.extension.ext2.impl.Ext2Impl1
impl2=org.apache.dubbo.common.extension.ext2.impl.Ext2Impl2
impl3=org.apache.dubbo.common.extension.ext2.impl.Ext2Impl3

可以看出是個鍵值對。值爲實現類的全類名。

運行測試類得到如下

Dubbo SPI 除了支持按需加載接口實現類,還增加了 IOC 和 AOP 等特性。

上面簡單演示了 Dubbo SPI 的使用方法。我們首先通過 ExtensionLoader 的 getExtensionLoader 方法獲取一個 ExtensionLoader 實例,然後再通過 ExtensionLoader 的 getExtension 方法獲取拓展類對象。這其中,getExtensionLoader 方法用於從緩存中獲取與拓展類對應的 ExtensionLoader,若緩存未命中,則創建一個新的實例。該方法的邏輯比較簡單,本章就不進行分析了。下面我們從 ExtensionLoader 的 getExtension 方法作爲入口,對拓展類對象的獲取過程進行詳細的分析。

由於篇幅有限並且文章太長會讓讀者沒興趣看下去。下篇我們再來看Dubbo 的SPI 源碼。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章