国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

聊聊Dubbo - Dubbo可擴(kuò)展機(jī)制源碼解析

lmxdawn / 1033人閱讀

摘要:什么是類那什么樣類的才是擴(kuò)展機(jī)制中的類呢類是一個(gè)有復(fù)制構(gòu)造函數(shù)的類,也是典型的裝飾者模式。代碼如下有一個(gè)參數(shù)是的復(fù)制構(gòu)造函數(shù)有一個(gè)構(gòu)造函數(shù),參數(shù)是擴(kuò)展點(diǎn),所以它是一個(gè)擴(kuò)展機(jī)制中的類。

摘要:?在Dubbo可擴(kuò)展機(jī)制實(shí)戰(zhàn)中,我們了解了Dubbo擴(kuò)展機(jī)制的一些概念,初探了Dubbo中LoadBalance的實(shí)現(xiàn),并自己實(shí)現(xiàn)了一個(gè)LoadBalance。是不是覺(jué)得Dubbo的擴(kuò)展機(jī)制很不錯(cuò)呀,接下來(lái),我們就深入Dubbo的源碼,一睹廬山真面目。

在Dubbo可擴(kuò)展機(jī)制實(shí)戰(zhàn)中,我們了解了Dubbo擴(kuò)展機(jī)制的一些概念,初探了Dubbo中LoadBalance的實(shí)現(xiàn),并自己實(shí)現(xiàn)了一個(gè)LoadBalance。是不是覺(jué)得Dubbo的擴(kuò)展機(jī)制很不錯(cuò)呀,接下來(lái),我們就深入Dubbo的源碼,一睹廬山真面目。

ExtensionLoader
ExtentionLoader是最核心的類,負(fù)責(zé)擴(kuò)展點(diǎn)的加載和生命周期管理。我們就以這個(gè)類開(kāi)始吧。
Extension的方法比較多,比較常用的方法有:

public static ExtensionLoader getExtensionLoader(Class type)
public T getExtension(String name)
public T getAdaptiveExtension()
比較常見(jiàn)的用法有:

LoadBalance lb = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(loadbalanceName)
RouterFactory routerFactory = ExtensionLoader.getExtensionLoader(RouterFactory.class).getAdaptiveExtension()
說(shuō)明:在接下來(lái)展示的源碼中,我會(huì)將無(wú)關(guān)的代碼(比如日志,異常捕獲等)去掉,方便大家閱讀和理解。

*1. getExtensionLoader方法
這是一個(gè)靜態(tài)工廠方法,入?yún)⑹且粋€(gè)可擴(kuò)展的接口,返回一個(gè)該接口的ExtensionLoader實(shí)體類。通過(guò)這個(gè)實(shí)體類,可以根據(jù)name獲得具體的擴(kuò)展,也可以獲得一個(gè)自適應(yīng)擴(kuò)展。

public static ExtensionLoader getExtensionLoader(Class type) {

    // 擴(kuò)展點(diǎn)必須是接口
    if (!type.isInterface()) {
        throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
    }
    // 必須要有@SPI注解
    if (!withExtensionAnnotation(type)) {
        throw new IllegalArgumentException("Extension type without @SPI Annotation!");
    }
    // 從緩存中根據(jù)接口獲取對(duì)應(yīng)的ExtensionLoader
    // 每個(gè)擴(kuò)展只會(huì)被加載一次
    ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
    if (loader == null) {
        // 初始化擴(kuò)展
        EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
        loader = (ExtensionLoader) 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 holder = cachedInstances.get(name);
    if (holder == null) {
        cachedInstances.putIfAbsent(name, new Holder());
        holder = cachedInstances.get(name);
    }
    Object instance = holder.get();
    // 從緩存中獲取,如果不存在就創(chuàng)建
    if (instance == null) {
        synchronized (holder) {
            instance = holder.get();
            if (instance == null) {
                instance = createExtension(name);
                holder.set(instance);
            }
        }
    }
    return (T) instance;
}

getExtention方法中做了一些判斷和緩存,主要的邏輯在createExtension方法中。我們繼續(xù)看createExtention方法。

private T createExtension(String name) {

    // 根據(jù)擴(kuò)展點(diǎn)名稱得到擴(kuò)展類,比如對(duì)于LoadBalance,根據(jù)random得到RandomLoadBalance類
    Class clazz = getExtensionClasses().get(name);
    
    T instance = (T) EXTENSION_INSTANCES.get(clazz);
    if (instance == null) {
          // 使用反射調(diào)用nesInstance來(lái)創(chuàng)建擴(kuò)展類的一個(gè)示例
        EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
        instance = (T) EXTENSION_INSTANCES.get(clazz);
    }
    // 對(duì)擴(kuò)展類示例進(jìn)行依賴注入
    injectExtension(instance);
    // 如果有wrapper,添加wrapper
    Set> wrapperClasses = cachedWrapperClasses;
    if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
        for (Class wrapperClass : wrapperClasses) {
            instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
        }
    }
    return instance;

}

createExtension方法做了以下事情:
*1. 先根據(jù)name來(lái)得到對(duì)應(yīng)的擴(kuò)展類。從ClassPath下META-INF文件夾下讀取擴(kuò)展點(diǎn)配置文件。

*2. 使用反射創(chuàng)建一個(gè)擴(kuò)展類的實(shí)例

*3. 對(duì)擴(kuò)展類實(shí)例的屬性進(jìn)行依賴注入,即IoC。

*4. 如果有wrapper,添加wrapper,即AoP。

下面我們來(lái)重點(diǎn)看下這4個(gè)過(guò)程
*1. 根據(jù)name獲取對(duì)應(yīng)的擴(kuò)展類
先看代碼:

private Map> getExtensionClasses() {

    Map> classes = cachedClasses.get();
    if (classes == null) {
        synchronized (cachedClasses) {
            classes = cachedClasses.get();
            if (classes == null) {
                classes = loadExtensionClasses();
                cachedClasses.set(classes);
            }
        }
    }
    return classes;
}

// synchronized in getExtensionClasses
private Map> loadExtensionClasses() {
    final SPI defaultAnnotation = type.getAnnotation(SPI.class);
    if (defaultAnnotation != null) {
        String value = defaultAnnotation.value();
        if (value != null && (value = value.trim()).length() > 0) {
            String[] names = NAME_SEPARATOR.split(value);
            if (names.length > 1) {
                throw new IllegalStateException("more than 1 default extension name on extension " + type.getName());
            }
            if (names.length == 1) cachedDefaultName = names[0];
        }
    }

    Map> extensionClasses = new HashMap>();
    loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
    loadFile(extensionClasses, DUBBO_DIRECTORY);
    loadFile(extensionClasses, SERVICES_DIRECTORY);
    return extensionClasses;
}

過(guò)程很簡(jiǎn)單,先從緩存中獲取,如果沒(méi)有,就從配置文件中加載。配置文件的路徑就是之前提到的:

META-INF/dubbo/internal
META-INF/dubbo
META-INF/services
*2. 使用反射創(chuàng)建擴(kuò)展實(shí)例
這個(gè)過(guò)程很簡(jiǎn)單,使用clazz.newInstance())來(lái)完成。創(chuàng)建的擴(kuò)展實(shí)例的屬性都是空值。

*3. 擴(kuò)展實(shí)例自動(dòng)裝配
在實(shí)際的場(chǎng)景中,類之間都是有依賴的。擴(kuò)展實(shí)例中也會(huì)引用一些依賴,比如簡(jiǎn)單的Java類,另一個(gè)Dubbo的擴(kuò)展或一個(gè)Spring Bean等。依賴的情況很復(fù)雜,Dubbo的處理也相對(duì)復(fù)雜些。我們稍后會(huì)有專門(mén)的章節(jié)對(duì)其進(jìn)行說(shuō)明,現(xiàn)在,我們只需要知道,Dubbo可以正確的注入擴(kuò)展點(diǎn)中的普通依賴,Dubbo擴(kuò)展依賴或Spring依賴等。

*4. 擴(kuò)展實(shí)例自動(dòng)包裝
自動(dòng)包裝就是要實(shí)現(xiàn)類似于Spring的AOP功能。Dubbo利用它在內(nèi)部實(shí)現(xiàn)一些通用的功能,比如日志,監(jiān)控等。關(guān)于擴(kuò)展實(shí)例自動(dòng)包裝的內(nèi)容,也會(huì)在后面多帶帶講解。

經(jīng)過(guò)上面的4步,Dubbo就創(chuàng)建并初始化了一個(gè)擴(kuò)展實(shí)例。這個(gè)實(shí)例的依賴被注入了,也根據(jù)需要被包裝了。到此為止,這個(gè)擴(kuò)展實(shí)例就可以被使用了。

Dubbo SPI高級(jí)用法之自動(dòng)裝配
自動(dòng)裝配的相關(guān)代碼在injectExtension方法中:

private T injectExtension(T instance) {

for (Method method : instance.getClass().getMethods()) {
    if (method.getName().startsWith("set")
            && method.getParameterTypes().length == 1
            && Modifier.isPublic(method.getModifiers())) {
        Class pt = method.getParameterTypes()[0];
      
        String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
        Object object = objectFactory.getExtension(pt, property);
        if (object != null) {
            method.invoke(instance, object);
        }
    }
}
return instance;

}

要實(shí)現(xiàn)對(duì)擴(kuò)展實(shí)例的依賴的自動(dòng)裝配,首先需要知道有哪些依賴,這些依賴的類型是什么。Dubbo的方案是查找Java標(biāo)準(zhǔn)的setter方法。即方法名以set開(kāi)始,只有一個(gè)參數(shù)。如果擴(kuò)展類中有這樣的set方法,Dubbo會(huì)對(duì)其進(jìn)行依賴注入,類似于Spring的set方法注入。
但是Dubbo中的依賴注入比Spring要復(fù)雜,因?yàn)镾pring注入的都是Spring bean,都是由Spring容器來(lái)管理的。而Dubbo的依賴注入中,需要注入的可能是另一個(gè)Dubbo的擴(kuò)展,也可能是一個(gè)Spring Bean,或是Google guice的組件,或其他任何一個(gè)框架中的組件。Dubbo需要能夠從任何一個(gè)場(chǎng)景中加載擴(kuò)展。在injectExtension方法中,是用Object object = objectFactory.getExtension(pt, property)來(lái)實(shí)現(xiàn)的。objectFactory是ExtensionFactory類型的,在創(chuàng)建ExtensionLoader時(shí)被初始化:

private ExtensionLoader(Class type) {

    this.type = type;
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

objectFacory本身也是一個(gè)擴(kuò)展,通過(guò)ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension())來(lái)獲取。

ExtensionLoader有三個(gè)實(shí)現(xiàn):
*1. SpiExtensionLoader:Dubbo自己的Spi去加載Extension

*2. SpringExtensionLoader:從Spring容器中去加載Extension

*3. AdaptiveExtensionLoader: 自適應(yīng)的AdaptiveExtensionLoader

這里要注意AdaptiveExtensionLoader,源碼如下:

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

private final List factories;

public AdaptiveExtensionFactory() {
    ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
    List list = new ArrayList();
    for (String name : loader.getSupportedExtensions()) {
        list.add(loader.getExtension(name));
    }
    factories = Collections.unmodifiableList(list);
}

public  T getExtension(Class type, String name) {
    for (ExtensionFactory factory : factories) {
        T extension = factory.getExtension(type, name);
        if (extension != null) {
            return extension;
        }
    }
    return null;
}

}

AdaptiveExtensionLoader類有@Adaptive注解。前面提到了,Dubbo會(huì)為每一個(gè)擴(kuò)展創(chuàng)建一個(gè)自適應(yīng)實(shí)例。如果擴(kuò)展類上有@Adaptive,會(huì)使用該類作為自適應(yīng)類。如果沒(méi)有,Dubbo會(huì)為我們創(chuàng)建一個(gè)。所以ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension())會(huì)返回一個(gè)AdaptiveExtensionLoader實(shí)例,作為自適應(yīng)擴(kuò)展實(shí)例。
AdaptiveExtentionLoader會(huì)遍歷所有的ExtensionFactory實(shí)現(xiàn),嘗試著去加載擴(kuò)展。如果找到了,返回。如果沒(méi)有,在下一個(gè)ExtensionFactory中繼續(xù)找。Dubbo內(nèi)置了兩個(gè)ExtensionFactory,分別從Dubbo自身的擴(kuò)展機(jī)制和Spring容器中去尋找。由于ExtensionFactory本身也是一個(gè)擴(kuò)展點(diǎn),我們可以實(shí)現(xiàn)自己的ExtensionFactory,讓Dubbo的自動(dòng)裝配支持我們自定義的組件。比如,我們?cè)陧?xiàng)目中使用了Google的guice這個(gè)IoC容器。我們可以實(shí)現(xiàn)自己的GuiceExtensionFactory,讓Dubbo支持從guice容器中加載擴(kuò)展。

Dubbo SPI高級(jí)用法之AoP
在用Spring的時(shí)候,我們經(jīng)常會(huì)用到AOP功能。在目標(biāo)類的方法前后插入其他邏輯。比如通常使用Spring AOP來(lái)實(shí)現(xiàn)日志,監(jiān)控和鑒權(quán)等功能。
Dubbo的擴(kuò)展機(jī)制,是否也支持類似的功能呢?答案是yes。在Dubbo中,有一種特殊的類,被稱為Wrapper類。通過(guò)裝飾者模式,使用包裝類包裝原始的擴(kuò)展點(diǎn)實(shí)例。在原始擴(kuò)展點(diǎn)實(shí)現(xiàn)前后插入其他邏輯,實(shí)現(xiàn)AOP功能。

什么是Wrapper類
那什么樣類的才是Dubbo擴(kuò)展機(jī)制中的Wrapper類呢?Wrapper類是一個(gè)有復(fù)制構(gòu)造函數(shù)的類,也是典型的裝飾者模式。下面就是一個(gè)Wrapper類:

class A{

private A a;
public A(A a){
    this.a = a;
}

}

類A有一個(gè)構(gòu)造函數(shù)public A(A a),構(gòu)造函數(shù)的參數(shù)是A本身。這樣的類就可以成為Dubbo擴(kuò)展機(jī)制中的一個(gè)Wrapper類。Dubbo中這樣的Wrapper類有ProtocolFilterWrapper, ProtocolListenerWrapper等, 大家可以查看源碼加深理解。

怎么配置Wrapper類
在Dubbo中Wrapper類也是一個(gè)擴(kuò)展點(diǎn),和其他的擴(kuò)展點(diǎn)一樣,也是在META-INF文件夾中配置的。比如前面舉例的ProtocolFilterWrapper和ProtocolListenerWrapper就是在路徑dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol中配置的:

filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=com.alibaba.dubbo.rpc.support.MockProtocol

在Dubbo加載擴(kuò)展配置文件時(shí),有一段如下的代碼:

try {
clazz.getConstructor(type);
Set> wrappers = cachedWrapperClasses;
if (wrappers == null) {

cachedWrapperClasses = new ConcurrentHashSet>();
wrappers = cachedWrapperClasses;

}
wrappers.add(clazz);
} catch (NoSuchMethodException e) {}

這段代碼的意思是,如果擴(kuò)展類有復(fù)制構(gòu)造函數(shù),就把該類存起來(lái),供以后使用。有復(fù)制構(gòu)造函數(shù)的類就是Wrapper類。通過(guò)clazz.getConstructor(type)來(lái)獲取參數(shù)是擴(kuò)展點(diǎn)接口的構(gòu)造函數(shù)。注意構(gòu)造函數(shù)的參數(shù)類型是擴(kuò)展點(diǎn)接口,而不是擴(kuò)展類。
以Protocol為例。配置文件dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol中定義了filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper。
ProtocolFilterWrapper代碼如下:

public class ProtocolFilterWrapper implements Protocol {

private final Protocol protocol;

// 有一個(gè)參數(shù)是Protocol的復(fù)制構(gòu)造函數(shù)
public ProtocolFilterWrapper(Protocol protocol) {
    if (protocol == null) {
        throw new IllegalArgumentException("protocol == null");
    }
    this.protocol = protocol;
}

ProtocolFilterWrapper有一個(gè)構(gòu)造函數(shù)public ProtocolFilterWrapper(Protocol protocol),參數(shù)是擴(kuò)展點(diǎn)Protocol,所以它是一個(gè)Dubbo擴(kuò)展機(jī)制中的Wrapper類。ExtensionLoader會(huì)把它緩存起來(lái),供以后創(chuàng)建Extension實(shí)例的時(shí)候,使用這些包裝類依次包裝原始擴(kuò)展點(diǎn)。

擴(kuò)展點(diǎn)自適應(yīng)
前面講到過(guò),Dubbo需要在運(yùn)行時(shí)根據(jù)方法參數(shù)來(lái)決定該使用哪個(gè)擴(kuò)展,所以有了擴(kuò)展點(diǎn)自適應(yīng)實(shí)例。其實(shí)是一個(gè)擴(kuò)展點(diǎn)的代理,將擴(kuò)展的選擇從Dubbo啟動(dòng)時(shí),延遲到RPC調(diào)用時(shí)。Dubbo中每一個(gè)擴(kuò)展點(diǎn)都有一個(gè)自適應(yīng)類,如果沒(méi)有顯式提供,Dubbo會(huì)自動(dòng)為我們創(chuàng)建一個(gè),默認(rèn)使用Javaassist。
先來(lái)看下創(chuàng)建自適應(yīng)擴(kuò)展類的代碼:

public T getAdaptiveExtension() {

Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
        synchronized (cachedAdaptiveInstance) {
            instance = cachedAdaptiveInstance.get();
            if (instance == null) {
                  instance = createAdaptiveExtension();
                  cachedAdaptiveInstance.set(instance); 
            }
        }        
}

return (T) instance;

}

繼續(xù)看createAdaptiveExtension方法

private T createAdaptiveExtension() {

return injectExtension((T) getAdaptiveExtensionClass().newInstance());

}

繼續(xù)看getAdaptiveExtensionClass方法

private Class getAdaptiveExtensionClass() {

    getExtensionClasses();
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

繼續(xù)看createAdaptiveExtensionClass方法,繞了一大圈,終于來(lái)到了具體的實(shí)現(xiàn)了。看這個(gè)createAdaptiveExtensionClass方法,它首先會(huì)生成自適應(yīng)類的Java源碼,然后再將源碼編譯成Java的字節(jié)碼,加載到JVM中。

private Class createAdaptiveExtensionClass() {

    String code = createAdaptiveExtensionClassCode();
    ClassLoader classLoader = findClassLoader();
    com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
    return compiler.compile(code, classLoader);
}

Compiler的代碼,默認(rèn)實(shí)現(xiàn)是javassist。

@SPI("javassist")
public interface Compiler {

Class compile(String code, ClassLoader classLoader);

}

createAdaptiveExtensionClassCode()方法中使用一個(gè)StringBuilder來(lái)構(gòu)建自適應(yīng)類的Java源碼。方法實(shí)現(xiàn)比較長(zhǎng),這里就不貼代碼了。這種生成字節(jié)碼的方式也挺有意思的,先生成Java源代碼,然后編譯,加載到j(luò)vm中。通過(guò)這種方式,可以更好的控制生成的Java類。而且這樣也不用care各個(gè)字節(jié)碼生成框架的api等。因?yàn)閤xx.java文件是Java通用的,也是我們最熟悉的。只是代碼的可讀性不強(qiáng),需要一點(diǎn)一點(diǎn)構(gòu)建xx.java的內(nèi)容。
下面是使用createAdaptiveExtensionClassCode方法為Protocol創(chuàng)建的自適應(yīng)類的Java代碼范例:

package com.alibaba.dubbo.rpc;

import com.alibaba.dubbo.common.extension.ExtensionLoader;

public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {

public void destroy() {
    throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
}

public int getDefaultPort() {
    throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
}

public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
    if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
    if (arg0.getUrl() == null)
        throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
    com.alibaba.dubbo.common.URL url = arg0.getUrl();
    String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
    if (extName == null)
        throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
    com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
    return extension.export(arg0);
}

public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {
    if (arg1 == null) throw new IllegalArgumentException("url == null");
    com.alibaba.dubbo.common.URL url = arg1;
    String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());
    if (extName == null)
        throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
    com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
    return extension.refer(arg0, arg1);
}

}

大致的邏輯和開(kāi)始說(shuō)的一樣,通過(guò)url解析出參數(shù),解析的邏輯由@Adaptive的value參數(shù)控制,然后再根據(jù)得到的擴(kuò)展點(diǎn)名獲取擴(kuò)展點(diǎn)實(shí)現(xiàn),然后進(jìn)行調(diào)用。如果大家想知道具體的構(gòu)建.java代碼的邏輯,可以看createAdaptiveExtensionClassCode的完整實(shí)現(xiàn)。
在生成的Protocol$Adpative中,發(fā)現(xiàn)getDefaultPort和destroy方法都是直接拋出異常的,這是為什么呢?來(lái)看看Protocol的源碼:

@SPI("dubbo")
public interface Protocol {

int getDefaultPort();

@Adaptive
 Exporter export(Invoker invoker) throws RpcException;

@Adaptive
 Invoker refer(Class type, URL url) throws RpcException;

void destroy();

可以看到Protocol接口中有4個(gè)方法,但只有export和refer兩個(gè)方法使用了@Adaptive注解。Dubbo自動(dòng)生成的自適應(yīng)實(shí)例,只有@Adaptive修飾的方法才有具體的實(shí)現(xiàn)。所以,Protocol$Adpative類中,也只有export和refer這兩個(gè)方法有具體的實(shí)現(xiàn),其余方法都是拋出異常。

原文鏈接

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/69668.html

相關(guān)文章

  • 聊聊Dubbo - Dubbo擴(kuò)展機(jī)制實(shí)戰(zhàn)

    摘要:今天我想聊聊的另一個(gè)很棒的特性就是它的可擴(kuò)展性。的擴(kuò)展機(jī)制在的官網(wǎng)上,描述自己是一個(gè)高性能的框架。接下來(lái)的章節(jié)中我們會(huì)慢慢揭開(kāi)擴(kuò)展機(jī)制的神秘面紗。擴(kuò)展擴(kuò)展點(diǎn)的實(shí)現(xiàn)類。的定義在配置文件中可以看到文件中定義了個(gè)的擴(kuò)展實(shí)現(xiàn)。 摘要: 在Dubbo的官網(wǎng)上,Dubbo描述自己是一個(gè)高性能的RPC框架。今天我想聊聊Dubbo的另一個(gè)很棒的特性, 就是它的可擴(kuò)展性。 Dubbo的擴(kuò)展機(jī)制 在Dub...

    techstay 評(píng)論0 收藏0
  • dubbo源碼解析(二)Dubbo擴(kuò)展機(jī)制SPI

    摘要:二注解該注解為了保證在內(nèi)部調(diào)用具體實(shí)現(xiàn)的時(shí)候不是硬編碼來(lái)指定引用哪個(gè)實(shí)現(xiàn),也就是為了適配一個(gè)接口的多種實(shí)現(xiàn),這樣做符合模塊接口設(shè)計(jì)的可插拔原則,也增加了整個(gè)框架的靈活性,該注解也實(shí)現(xiàn)了擴(kuò)展點(diǎn)自動(dòng)裝配的特性。 Dubbo擴(kuò)展機(jī)制SPI 前一篇文章《dubbo源碼解析(一)Hello,Dubbo》是對(duì)dubbo整個(gè)項(xiàng)目大體的介紹,而從這篇文章開(kāi)始,我將會(huì)從源碼來(lái)解讀dubbo再各個(gè)模塊的實(shí)...

    DirtyMind 評(píng)論0 收藏0
  • dubbo源碼解析(八)遠(yuǎn)程通信——開(kāi)篇

    摘要:而編碼器是講應(yīng)用程序的數(shù)據(jù)轉(zhuǎn)化為網(wǎng)絡(luò)格式,解碼器則是講網(wǎng)絡(luò)格式轉(zhuǎn)化為應(yīng)用程序,同時(shí)具備這兩種功能的單一組件就叫編解碼器。在中是老的編解碼器接口,而是新的編解碼器接口,并且已經(jīng)用把適配成了。 遠(yuǎn)程通訊——開(kāi)篇 目標(biāo):介紹之后解讀遠(yuǎn)程通訊模塊的內(nèi)容如何編排、介紹dubbo-remoting-api中的包結(jié)構(gòu)設(shè)計(jì)以及最外層的的源碼解析。 前言 服務(wù)治理框架中可以大致分為服務(wù)通信和服務(wù)管理兩個(gè)...

    Faremax 評(píng)論0 收藏0
  • dubbo源碼解析(一)Hello,Dubbo

    摘要:英文全名為,也叫遠(yuǎn)程過(guò)程調(diào)用,其實(shí)就是一個(gè)計(jì)算機(jī)通信協(xié)議,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù)而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。 Hello,Dubbo 你好,dubbo,初次見(jiàn)面,我想和你交個(gè)朋友。 Dubbo你到底是什么? 先給出一套官方的說(shuō)法:Apache Dubbo是一款高性能、輕量級(jí)基于Java的RPC開(kāi)源框架。 那么什么是RPC? 文檔地址:http://dubbo.a...

    evin2016 評(píng)論0 收藏0
  • dubbo擴(kuò)展點(diǎn)機(jī)制

    摘要:在中配置,以配置為例整個(gè),最先使用的地方從里面讀取這個(gè)配置使用接口的中獲取具體的實(shí)現(xiàn)類中有兩個(gè)值當(dāng)主線程被外部終止時(shí),會(huì)觸發(fā),執(zhí)行的與方法通知下面的鎖操作,主線程正常走完代碼,并最終停止。 spring是如何啟動(dòng)容器的 常見(jiàn)的一種在本地使用main方法啟動(dòng)spring的方法 public static void main(String[] args) throws Except...

    Rindia 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<