探究Dubbo的ExtensionLoader

必定要對比JDK的SPI機制,才能更好的理解Dubbo的SPI實現!java

擴展點:即接口
擴展:擴展點的實現,即接口的實現類
  1. 獲取擴展點的ServiceLoader實例spring

  2. 經過擴展點的ServiceLoader實例,完成擴展的方法調用緩存

package com.nucc;
​
import java.util.ServiceLoader;
​
/**
 * JDK SPI Sample.
 */
public class App {
    public static void main(String[] args) {
        ServiceLoader<Command> serviceLoader = ServiceLoader.load(Command.class);
​
        for (Command cmd : serviceLoader) {
            cmd.execute();
        }
    }
}

經過以上代碼理解了JDK的SPI機制,那麼DUBBO SPI機制該怎麼實現?框架

1⃣ 獲取擴展點的ExtensionLoader實例,但願它是單例的,初始化後將它緩存起來(方便之後拿出來直接用);設計

2⃣ 獲取擴展的實例,爲了不JDK SPI中一次所有加載帶來的資源損耗問題,Dubbo SPI機制應在設計上應採用延遲加載機制,即只獲取想要的擴展,而非將所有擴展進行加載。代理

深刻探究Dubbo的ExtensionLoaderxml

  1. getExtensionLoader(Class<?> type) : 單例模式,獲取接口type的ExtensionLoader實例,擴展上必須添加@SPI註解,對於擴展點只會加載一次,生成一個ExtensionLoader實例,放入緩存中。對象

  2. getAdaptiveExtension() :獲取擴展點的實現,dubbo框架在調用getAdaptiveExtension()中,將配置文件中的META-INF\dubbo\internal下全部的配置初始化加載到緩存中,這個方法會首先在擴展點接口的全部實現類中查找類上是否含有@Adaptive註解,若是有這個樣的類註解返回該類的實例,若是沒有則會查找擴展點接口的方法是否有@Adaptive註解,並動態編譯一個類實現該接口並擴展這些含有@Adaptive註解的方法。默認將採用@SPI註解value指定的擴展。若是開發者選擇使用其它擴展,則在dubbo的spring xml配置中指定。Dubbo使用「自適應」的擴展,在運行時經過URL中的配置參數決定採用哪個擴展的方案,解決了JDK SPI中一次所有加載帶來的資源損耗問題。接口

    若是用@Adaptive標記一個類,表示該類是一個自適應的擴展點實現,目前系統只有兩個:AdaptiveCompiler(整個框架僅支持Javassist和JdkCompiler)和AdaptiveExtensionFactory(整個框架僅支持2個objFactory,一個是spi,另外一個是spring);資源

    若是用@Adaptive標記一個方法,則dubbo會動態生成一個擴展點的實現,例如Protocol$Adaptive(dubbo的動態代碼生成與編譯),該擴展點代碼實現是經過javassit技術動態建立的類,並由dubbo編譯加載。

    --> 面向對象設計的「開閉原則」,以及動態代理模式

    在上述流程中,生成一個擴展點的實例(適配器類)時,須要完成依賴的注入,Dubbo採用ExtensionFactory擴展點的實現來完成(SPI和Spring),即採用injectExtension方法爲適配器的setter方法插入其它擴展點的實現或者Spring中的bean,此處爲dubbo的Ioc設計。

  3. getExtension(String name) : 獲取指定名字的擴展

相關文章
相關標籤/搜索