Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive

目录

1、前文

2、Dubbo SP

第一步 首先获取对应的ExtensionLoader对象

二 代码中缓存对象

2.1 private final Holder>> cachedClasses = new Holder<>();

2.2  cachedAdaptiveClass

2.3 cachedAdaptiveInstance 缓存扩展类的instance 

3 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()过程

3.1、ExtensionLoader loader 中只有一个type属性对应

3.2、调用getAdaptiveExtension方法:

获取到ObjectFactory后返回对应的ExtensionLoader

四 第二步 首先通过getAdaptiveExtension回去自适应对象

五 ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);做了什么?


 


1、前文

在前面四章进行了了解dubbo中的默认服务发现、调用等逻辑后,本章对Dubbo中使用的SPI技术进行了解。

SPI全称为Service Provider Interface,Java SPI可以自行了解,本文不做叙述。

2、Dubbo SP

案例一:ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

首先查看getExtensionLoader方法做了什么:

第一步 首先获取对应的ExtensionLoader对象

    @SuppressWarnings("unchecked")
    public static  ExtensionLoader getExtensionLoader(Class type) {
        if (type == null) { // 判空
            throw new IllegalArgumentException("Extension type == null");
        }
        if (!type.isInterface()) { // 判断是否为接口
            throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
        }
        if (!withExtensionAnnotation(type)) {// 判断接口是否使用了@SPI注解
            throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
        }
        // 初次加载为null  需要进行new
        ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
        if (loader == null) {
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type)); //根据type生成指定的ExtensionLoader
            loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }

首先是对其进行一些列的参数校验等,然后通过

    private ExtensionLoader(Class type) {
        this.type = type;
        // 首先生成指定的ExtensionFactory的自适应扩展类   Adaptive根据参数动态配置
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

此处type为ExtensionFactory的时候直接用null否则通过ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() 生成对应的

ExtensionFactory

二 代码中缓存对象

@Adaptive @Spi等注解来表示对应是自适应扩展类,或是spi等

实际就是根据不同文件路径的对象进行缓存响应的class信息等

private static final String SERVICES_DIRECTORY = "META-INF/services/";

private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";

private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";

代码中进行各种缓存的存入,如封装类的缓存、实例缓存等

    private Map> loadExtensionClasses() {
        cacheDefaultExtensionName();

        Map> extensionClasses = new HashMap<>();
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
        return extensionClasses; // 根据type.getName获取指定文件下的key,和value映射 如spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory
    }

2.1 private final Holder>> cachedClasses = new Holder<>();

Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive_第1张图片

表示根据type获取指定配置文件下的key,value(指定类的Class对象)映射如:

spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory

Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive_第2张图片

2.2  cachedAdaptiveClass

adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory

根据配置文件中adaptive对应的value找到AdaptiveClass进行缓存

 

2.3 cachedAdaptiveInstance 缓存扩展类的instance 

如2.2中AdaptiveExtensionFactory的实例

3 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()过程

3.1、ExtensionLoader loader 中只有一个type属性对应

interface org.apache.dubbo.common.extension.ExtensionFactory

3.2、调用getAdaptiveExtension方法:

根据adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory 来进行实现扩展,即

AdaptiveExtensionFactory实例对象,其中对象
private final List factories;
    public AdaptiveExtensionFactory() {
        ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List list = new ArrayList();
        for (String name : loader.getSupportedExtensions()) { // 获取对应的key,如spi等 从对应的cachedClasses 获取到对应的实例进行具体化然后放入list
            //如那么为spi则表示spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory 对应的factory
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

获取到ObjectFactory后返回对应的ExtensionLoader

此时的对象为:

Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive_第3张图片

四 第二步 首先通过getAdaptiveExtension回去自适应对象

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

对ExtensionClasses的信息查询过程发现对应的文件目录下未指定对应的

adaptive=""的protocol相关类的信息,因此调用
createAdaptiveExtensionClass

通过debug发现

String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
public void destroy()  {
throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort()  {
throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
if (arg1 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg1;
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.refer(arg0, arg1);
}
public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
org.apache.dubbo.common.URL url = arg0.getUrl();
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.export(arg0);
}
}

因为接口中指定cachedDefaultName为dubbo

@SPI("dubbo")
public interface Protocol 
    private Class createAdaptiveExtensionClass() {
        String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
        ClassLoader classLoader = findClassLoader();
        org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        return compiler.compile(code, classLoader);
    }

获取加载类,和org.apache.dubbo.common.compiler.support.AdaptiveCompiler,进行生成对应的class信息,生成一个自适应的protocol实现类。

具体实现方法会根据

org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.export(arg0);

进行export。

五 ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);做了什么?

主要代码 getExtension(extName)其中name为默认协议"dubbo",表示根据dubbo找到对应的DubboProtocol

dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
    public T getExtension(String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalArgumentException("Extension name == null");
        }
        if ("true".equals(name)) {
            return getDefaultExtension();
        }
        final Holder holder = getOrCreateHolder(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;
    } 
  

Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive_第4张图片

发现最终是DubboProtocol的一个封装,具体原因在org.apache.dubbo.common.extension.ExtensionLoader#createExtension中

会进行

            injectExtension(instance);
            Set> wrapperClasses = cachedWrapperClasses;
            if (CollectionUtils.isNotEmpty(wrapperClasses)) {
                for (Class wrapperClass : wrapperClasses) {
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }

Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive_第5张图片

通过

private Set> cachedWrapperClasses;

对其进行装饰最终生成对应的

ProtocolListenerWrapper

你可能感兴趣的:(dubbo源码分析,dubbo)