【DUBBO】 扩展机制ServiceLoaderExtensionLoader

可扩展机制也就是SPI(Service Provider Interface)了,SPI是一种服务提供发现机制。一个服务通常指的是已知的接口,服务提供方就是这个接口的实现类,然后按照SPI标准存放到资源路径META-INF/services目录下,文件的命名为该服务接口的全限定名。

JDK默认提供一种SPI实现,即:ServiceLoader,但它功能有限,例如:不能依赖注入、不能根据扩展实现类标识符获取特定的扩展实现类实例;Dubbo也提供了一种SPI实现,即:ExtensionLoader,功能比较强大。因为在前面的两篇总结中大量的用到了dubbo的SPI机制,所以有必要对它的实现原理做一个详细分析。

ServiceLoader

测试案例

有一个服务

package com.zto.sxy.helloworld;

public interface ISPI {
    void say();
}

实现类SPITestA

package com.zto.sxy.helloworld;

public class SPITestA implements ISPI{
    @Override
    public void say() {
        System.out.println("SPI with implement testA");
    }
}

实现类SPITestB

package com.zto.sxy.helloworld;

public class SPITestB implements ISPI{
    @Override
    public void say() {
        System.out.println("SPI with implement testB");
    }
}

然后在resources目录下添加META-INF/services文件夹,同时新建一个名为com.zto.sxy.helloworld.ISPI的文件,内容如下:

com.zto.sxy.helloworld.SPITestA

com.zto.sxy.helloworld.SPITestB

以下是测试类

public class TestSPI {
    @Test
    public void testWithNoSPI(){
        ISPI testA = new SPITestA();
        testA.say();

        ISPI testB = new SPITestB();
        testB.say();
    }
    
    @Test
    public void testWithSPI(){
        ServiceLoader services = ServiceLoader.load(ISPI.class);
        for (Iterator<ISPI> iterator = services.iterator(); iterator.hasNext(); ) {
            ISPI spi = iterator.next();
            spi.say();
        }
    }
}

执行测试函数,发现两个输出结果一样,说明SPI生效了,输出结果如下:

SPI with implement testA
SPI with implement testB

实现原理

先看load方法

public static <S> ServiceLoader<S> load(Class<S> service) {
    // 获取当前线程上下文类加载器
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    return ServiceLoader.load(service, cl);
}

public static <S> ServiceLoader<S> load(Class<S> service,ClassLoader loader){
    return new ServiceLoader<>(service, loader);
}

private ServiceLoader(Class<S> svc, ClassLoader cl) {
    // 确保Class参数不为空
    service = Objects.requireNonNull(svc, "Service interface cannot be null");
    loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
    acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;

    // 清空缓存,确保会重新加载
    reload();
}

在调用的的时候,先通过调用iterator方法返回一个Iterator对象,然后遍历该Iterator对象

public Iterator<S> iterator() {
    return new Iterator<S>() {
        //     private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
        Iterator<Map.Entry<String,S>> knownProviders
            = providers.entrySet().iterator();

        public boolean hasNext() {
            if (knownProviders.hasNext())
                return true;
            return lookupIterator.hasNext();
        }

        public S next() {
            if (knownProviders.hasNext())
                return knownProviders.next().getValue();
            return lookupIterator.next();
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

    };
}

调用hasNext方法的时候,会调用lookupIterator.hasNext()

private boolean hasNextService() {
    if (nextName != null) {
        return true;
    }
    if (configs == null) {
        try {
            String fullName = PREFIX + service.getName();
            if (loader == null)
                configs = ClassLoader.getSystemResources(fullName);
            else
                configs = loader.getResources(fullName);
        } catch (IOException x) {
            fail(service, "Error locating configuration files", x);
        }
    }
    while ((pending == null) || !pending.hasNext()) {
        if (!configs.hasMoreElements()) {
            return false;
        }

        // 获取所有类的全类名
        pending = parse(service, configs.nextElement());
    }
  
    nextName = pending.next();
    return true;
}

当调用next方法的时候

private S nextService() {
    if (!hasNextService())
        throw new NoSuchElementException();
    String cn = nextName;
    nextName = null;
    Class<?> c = null;
    try {
        // 生成Class对象
        c = Class.forName(cn, false, loader);
    } catch (ClassNotFoundException x) {
        fail(service,
                "Provider " + cn + " not found");
    }
    if (!service.isAssignableFrom(c)) {
        fail(service,
                "Provider " + cn  + " not a subtype");
    }
    try {
        // 实例化
        S p = service.cast(c.newInstance());
        providers.put(cn, p);
        return p;
    } catch (Throwable x) {
        fail(service,
                "Provider " + cn + " could not be instantiated",
                x);
    }
    throw new Error();          // This cannot happen
}

ServiceLoader不是一实例化以后立马就去读配置文件中的服务实现者并实例化,而是等其Iterator实现获取对应的服务提供者时才会加载对应的配置文件进行解析,在调用Iterator的hasNext方法时会去加载配置文件进行解析,在调用next方法时会将对应的服务提供者进行实例化并进行缓存。

ExtensionLoader

大佬博客

测试案例

@Test
public void test(){
    Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension("dubbo");

    protocol.destroy();
}

实现原理

在此之前,先看看ExtensionLoader中一些属性的含义

快速预览
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.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 static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");

// 所有ExtensionLoader实例共享,缓存 对应扩展接口:ExtensionLoader实例
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();

// 所有ExtensionLoader实例共享,缓存 对应实现类class对象:对应的实现类实例
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>();

// 扩展接口Class对象
private final Class<?> type;

private final ExtensionFactory objectFactory;

// 缓存 实现类Class对象:实现类标识
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();

// 缓存当前扩展下所有实现类的 Class对象
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();

// 缓存带有@Active注解的实现类,实现类标识:实现类Class对象,@Active注解表示该扩展实现类的激活条件和时机
private final Map<String, Object> cachedActivates = new ConcurrentHashMap<>();

// 缓存 实现类标识:Holder,因为种扩展都对应一个ExtensionLoader实例,所以通过实现类标识可以区分实现类
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();

// 缓存 带有@Adaptive注解的实现类的实例,因为每种扩展只能有一个实现类带有@Adaptive注解
private final Holder<Object> cachedAdaptiveInstance = new Holder<>();

// 缓存 带有@Adaptive注解的实现类Class对象,因为每种扩展只能有一个实现类带有@Adaptive注解
private volatile Class<?> cachedAdaptiveClass = null;

private String cachedDefaultName;
private volatile Throwable createAdaptiveInstanceError;

// 缓存 包装类 实现类里参数是接口类型的(如 com.alibaba.dubbo.rpc.Protocol类型,并且只有1个参数)的构造函数,表示它是个接口包装类
private Set<Class<?>> cachedWrapperClasses;

private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();
getExtensionLoader

getExtensionLoader是一个静态方法,用于获取一个ExtensionLoader实例,每种扩展对应一个ExtensionLoader实例,缓存在一个静态ConcurrentMap中

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    if (type == null)
        throw new IllegalArgumentException("Extension type == null");
    if (!type.isInterface()) {
        throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
    }

    // 检查是否有@SPI注解
    if (!withExtensionAnnotation(type)) {
        throw new IllegalArgumentException("Extension type(" + type +
                ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
    }

    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;
    // 在创建ExtensionLoader实例的过程中,涉及到和ExtensionFactory扩展相关的操作,这个在下面会有详细介绍
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
getExtension

每种扩展对应一个ExtensionLoader实例,每个ExtensionLoader实例中缓存了很多和当前扩展相关的信息,例如:该扩展的实现类、带有@Adaptive注解的扩展实现类、Wrapper实现类等等。getExtension主要是根据扩展实现类标识符获取对应的扩展实现类实例:

public T getExtension(String name) {
    if (name == null || name.length() == 0)
        throw new IllegalArgumentException("Extension name == null");
    if ("true".equals(name)) {
        return getDefaultExtension();
    }
    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;
}
createExtension
@SuppressWarnings("unchecked")
private T createExtension(String name) {
    // 先从当前ExtensionLoader实例中的缓存中获取Class对象,如果没有就加载SPI相关文件
    Class<?> clazz = getExtensionClasses().get(name);
    if (clazz == null) {
        throw findException(name);
    }
    try {
        // 同步到静态缓存
        T instance = (T) EXTENSION_INSTANCES.get(clazz);
        if (instance == null) {
            EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
            instance = (T) EXTENSION_INSTANCES.get(clazz);
        }

        // 完成接口实现类依赖注入,依赖组件先从SPI机制构造查找,再从Spring容器查找(完成第2步)
        injectExtension(instance);

        // 如果这些实现类有wrapper类,当前实例instance,注入到包装类,包装类有多个,依次层层,循环构造注入;最后返回的是,最后一个包装类实例,这也是dubbo的aop实现机制
        Set<Class<?>> wrapperClasses = cachedWrapperClasses;
        if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
            for (Class<?> wrapperClass : wrapperClasses) {
                instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
            }
        }
        return instance;
    } catch (Throwable t) {
        throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
                type + ")  could not be instantiated: " + t.getMessage(), t);
    }
}
getExtensionClasses

获取实现类的Class对象,在加载文件的过程中,会将相应的信息放入缓存中

private Map<String, Class<?>> getExtensionClasses() {
    // 从缓存中获取
    Map<String, Class<?>> classes = cachedClasses.get();
    if (classes == null) {
        synchronized (cachedClasses) {
            classes = cachedClasses.get();
            if (classes == null) {
                // 加载SPI相关文件
                classes = loadExtensionClasses();
                cachedClasses.set(classes);
            }
        }
    }
    return classes;
}

// synchronized in getExtensionClasses
private Map<String, Class<?>> loadExtensionClasses() {
    final SPI defaultAnnotation = type.getAnnotation(SPI.class);
    // 判断是否有@SPI注解
    if (defaultAnnotation != null) {
        String value = defaultAnnotation.value();
        if ((value = value.trim()).length() > 0) {
            String[] names = NAME_SEPARATOR.split(value);
            // 只能有一个默认值:SPI(value="xxx"),默认实现xxx
            if (names.length > 1) {
                throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
                        + ": " + Arrays.toString(names));
            }
            if (names.length == 1) cachedDefaultName = names[0];
        }
    }

    // 读取三个目录下的spi 配置文件;/META-INF/dubbo/internal, /META-INF/dubbo, /META-INF/services
    Map<String, Class<?>> 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;
}
依赖注入

在实例化扩展实现类的时候,该实现类可能会依赖一些其他的对象,主要有两种:一种是Spring容易中的Bean对象;另一种是其它的扩展实现类对象。

private T injectExtension(T instance) {
    try {
        if (objectFactory != null) {
            for (Method method : instance.getClass().getMethods()) {
                if (method.getName().startsWith("set")
                        && method.getParameterTypes().length == 1
                        && Modifier.isPublic(method.getModifiers())) {
                    // 获取所有public类型,并且只有一个参数的以set开头的方法

                    Class<?> pt = method.getParameterTypes()[0];
                    try {
                        // 构造驼峰命名法,得到该set方法的参数的类型,即:要注入的对应类型
                        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) {
                            // 执行set方法,完成注入
                            method.invoke(instance, object);
                        }
                    } catch (Exception e) {
                        logger.error("fail to inject via method " + method.getName()
                                + " of interface " + type.getName() + ": " + e.getMessage(), e);
                    }
                }
            }
        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return instance;
}
ExtensionFactory

有关于objectFactory对象,这里涉及到的内容比较多,在文章的开头已经提到过,这里详细解释一下

private ExtensionLoader(Class<?> type) {
    this.type = type;
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    if (type == null)
        throw new IllegalArgumentException("Extension type == null");
    if (!type.isInterface()) {
        throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
    }
    if (!withExtensionAnnotation(type)) {
        throw new IllegalArgumentException("Extension type(" + type +
                ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
    }

    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;
}
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).

当执行以上语句的时候:

  1. 先创建Protocol对应的ExtensionLoader实例对象
  2. 在执行1的过程中,涉及到ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()操作,所以会先创建ExtensionFactory对应的ExtensionLoader实例对象,然后返回一个ExtensionFactory对象,赋值给Protocol对应的ExtensionLoader实例对象。

ExtensionFactory其实也是一个扩展,并且它有一个带有@Adaptive注解的扩展实现类:AdaptiveExtensionFactory

@SPI
public interface ExtensionFactory {

    /**
     * Get extension.
     *
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);

}

而根据getAdaptiveExtension()方法的名字也可以猜测出,这里应该是创建了一个AdaptiveExtensionFactory对象

public T getAdaptiveExtension() {
    // 加载完SPI文件之后,如果有,就会放入缓存中
    Object instance = cachedAdaptiveInstance.get();
    if (instance == null) {
        if (createAdaptiveInstanceError == null) {
            synchronized (cachedAdaptiveInstance) {
                instance = cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        instance = createAdaptiveExtension();
                        cachedAdaptiveInstance.set(instance);
                    } catch (Throwable t) {
                        createAdaptiveInstanceError = t;
                        throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
                    }
                }
            }
        } else {
            throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
        }
    }

    return (T) instance;
}

private T createAdaptiveExtension() {
    try {
        // 也需要处理依赖注入
        return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    } catch (Exception e) {
        throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
    }
}

private Class<?> getAdaptiveExtensionClass() {
    // 这个方法有可能性触发SPI文件加载,当缓存中没有值得时候,就会加载SPI文件
    getExtensionClasses();
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }

    // 代表 @Adaptive注解添加在了方法上
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

以下是AdaptiveExtensionFactory对应的源码

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    private final List<ExtensionFactory> factories;

    public AdaptiveExtensionFactory() {
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List<ExtensionFactory> list = new ArrayList<>();
        // getSupportedExtensions()返回的是 非包装类扩展,非Adaptive扩展,防止无限循环
        for (String name : loader.getSupportedExtensions()) {
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

    @Override
    public <T> T getExtension(Class<T> type, String name) {
        // 除AdaptiveExtensionFactory外,依次调用所有ExtensionFactory实现类的getExtension方法,如果找到了,就直接退出
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }
}

SpiExtensionFactory 用于注入扩展实现类(非包装类扩展,非Adaptive扩展),SpringExtensionFactory用于注入Spring容器中的Bean。

getAdaptiveExtension

上面已经提到了getAdaptiveExtension方法,这个方法用于获取自适应的扩展实现类,这方法真的非常非常重要,在dubbo到处用到了这个特性。有关于@Adaptive注解,这里再详细说明一下: @Adaptive用法有两种方式,一种在就配置在扩展实现类上,用于扩展实现类上时只能有一个;还有一种直接配置在方法上,这两种方式第一种优先,没有第一种,dubbo自动完成第二种Adaptive类的生成

  1. 在扩展实现类上加上@Adaptive注解,是最为明确的创建对应类型Adaptive类,优先级最高;
  2. @SPI注解中的value是默认值,如果通过URL获取不到关于取哪个类作为Adaptive类的话,就使用这个默认值,当然如果URL中可以获取到,就用URL中的;
  3. 可以在方法上增加@Adaptive注解,注解中的value与链接中的参数的key一致,链接中的key对应的value就是SPI中的name,获取相应的实现类;

其实主要代码都在这里

private Class<?> getAdaptiveExtensionClass() {
    // 这个方法有可能性触发SPI文件加载,当缓存中没有值得时候,就会加载SPI文件
    getExtensionClasses();
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }

    // 动态生成
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

// 动态生成源码,然后编译返回Class对象
private Class<?> createAdaptiveExtensionClass() {
    // 创建代码的字符串形式
    String code = createAdaptiveExtensionClassCode();
    ClassLoader classLoader = findClassLoader();
    // 通过SPI获取java 编译器
    org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();

    // 编译源码返回Class对象
    return compiler.compile(code, classLoader);
}

以下以Protocol为例进行讲解,因为Protocol对应的扩展实现类上都没有加@Adaptive注解,所以这里主要涉及到Protocol$Adaptive类的动态生成

@SPI("dubbo")
public interface Protocol {
    @Adaptive
    <T> Exporter<T> export(Invoker<T> invoker) throws RpcException;

    @Adaptive
    <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException;
}

使用的场景可能是这样的

private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
Exporter<?> exporter = protocol.export(wrapperInvoker);

其动态生成的Protocol$Adaptive源码如下

package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;

public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
    private static final org.apache.dubbo.common.logger.Logger logger = org.apache.dubbo.common.logger.LoggerFactory.getLogger(ExtensionLoader.class);
    private java.util.concurrent.atomic.AtomicInteger count = new java.util.concurrent.atomic.AtomicInteger(0);

    public void destroy() {
        throw new UnsupportedOperationException("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("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("Fail to get extension(org.apache.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = null;
        try {
            extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        } catch (Exception e) {
            if (count.incrementAndGet() == 1) {
                logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.Protocol, will use default extension dubbo instead.", e);
            }
            extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension("dubbo");
        }
        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("Fail to get extension(org.apache.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
        org.apache.dubbo.rpc.Protocol extension = null;
        try {
            extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
        } catch (Exception e) {
            if (count.incrementAndGet() == 1) {
                logger.warn("Failed to find extension named " + extName + " for type org.apache.dubbo.rpc.Protocol, will use default extension dubbo instead.", e);
            }
            extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension("dubbo");
        }
        return extension.export(arg0);
    }
}

以export方法为例,从方法参数中Invoker获取信息, 如果没有,就取@SPI注解中的默认值:dubbo,如果都没有值,就抛出IllegalStateException异常

Wrapper处理

在处理完一个扩展实现类的依赖注入问题之后,接下来需要处理的便是该扩展实现类的Wrapper问题。在dubbo中,扩展实现类里参数是接口类型的(如 com.alibaba.dubbo.rpc.Protocol类型,并且只有1个参数)的构造函数,表示它是个Wrapper类。为什么需要它的构造函数需要有一个接口类型的参数?主要是用于接收上层对应的扩展实现类,然后Wrapper类实现类接口,所以可以在方法中插入一些自己的逻辑,类似于代理模式。 以ProtocolFilterWrapper为例,主要在于给非Wrapper扩展实现类加强功能

public class ProtocolFilterWrapper implements Protocol {

    private final Protocol protocol;

    public ProtocolFilterWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
    }

    @Override
    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
            return protocol.export(invoker);
        }
        return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
    }

    @Override
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
            return protocol.refer(type, url);
        }
        return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
    }
}

而有关于通过Wrappe类加强的逻辑

Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
    for (Class<?> wrapperClass : wrapperClasses) {
        instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
    }
}

就是将所有的Wrapper类包装在原始的扩展实现类上,在调用的时候,就会先执行所有Wrapper中对应的逻辑,然后再执行真正扩展实现类的逻辑。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券