聊聊Dubbo - Dubbo可擴展機制源碼解析

Dubbo可擴展機制實戰中,咱們瞭解了Dubbo擴展機制的一些概念,初探了Dubbo中LoadBalance的實現,並本身實現了一個LoadBalance。是否是以爲Dubbo的擴展機制很不錯呀,接下來,咱們就深刻Dubbo的源碼,一睹廬山真面目。緩存

ExtensionLoader

ExtentionLoader是最核心的類,負責擴展點的加載和生命週期管理。咱們就以這個類開始吧。
Extension的方法比較多,比較經常使用的方法有:app

  • public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type)
  • public T getExtension(String name)
  • public T getAdaptiveExtension()

比較常見的用法有:dom

  • LoadBalance lb = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName)
  • RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getAdaptiveExtension()

說明:在接下來展現的源碼中,我會將無關的代碼(好比日誌,異常捕獲等)去掉,方便你們閱讀和理解。this

*1. getExtensionLoader方法
這是一個靜態工廠方法,入參是一個可擴展的接口,返回一個該接口的ExtensionLoader實體類。經過這個實體類,能夠根據name得到具體的擴展,也能夠得到一個自適應擴展。spa

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
        // 擴展點必須是接口
        if (!type.isInterface()) {
            throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
        }
        // 必需要有@SPI註解
        if (!withExtensionAnnotation(type)) {
            throw new IllegalArgumentException("Extension type without @SPI Annotation!");
        }
        // 從緩存中根據接口獲取對應的ExtensionLoader
        // 每一個擴展只會被加載一次
        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        if (loader == null) {
            // 初始化擴展
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }
    
private ExtensionLoader(Class<?> type) {
        this.type = type;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

*2. getExtension方法日誌

public T getExtension(String name) {
        Holder<Object> holder = cachedInstances.get(name);
        if (holder == null) {
            cachedInstances.putIfAbsent(name, new Holder<Object>());
            holder = cachedInstances.get(name);
        }
        Object instance = holder.get();
        // 從緩存中獲取,若是不存在就建立
        if (instance == null) {
            synchronized (holder) {
                instance = holder.get();
                if (instance == null) {
                    instance = createExtension(name);
                    holder.set(instance);
                }
            }
        }
        return (T) instance;
    }

getExtention方法中作了一些判斷和緩存,主要的邏輯在createExtension方法中。咱們繼續看createExtention方法。code

private T createExtension(String name) {
        // 根據擴展點名稱獲得擴展類,好比對於LoadBalance,根據random獲得RandomLoadBalance類
        Class<?> clazz = getExtensionClasses().get(name);
        
        T instance = (T) EXTENSION_INSTANCES.get(clazz);
        if (instance == null) {
              // 使用反射調用nesInstance來建立擴展類的一個示例
            EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
            instance = (T) EXTENSION_INSTANCES.get(clazz);
        }
        // 對擴展類示例進行依賴注入
        injectExtension(instance);
        // 若是有wrapper,添加wrapper
        Set<Class<?>> wrapperClasses = cachedWrapperClasses;
        if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
            for (Class<?> wrapperClass : wrapperClasses) {
                instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
            }
        }
        return instance;
}

createExtension方法作了如下事情:
*1. 先根據name來獲得對應的擴展類。從ClassPath下META-INF文件夾下讀取擴展點配置文件。router

*2. 使用反射建立一個擴展類的實例接口

*3. 對擴展類實例的屬性進行依賴注入,即IoC。生命週期

*4. 若是有wrapper,添加wrapper,即AoP。

下面咱們來重點看下這4個過程 *1. 根據name獲取對應的擴展類 先看代碼:

相關文章
相關標籤/搜索