dubbo杂记-关于扩展点自适应

首先是扩展点

 dubbo定义了服务提供接口,接口与其的诸多实现一起组成了一个可扩展的应用,这是基于spi思想设计的,方便添加

一个新实现。以dubbo的protocol协议作为例子,首先定义了一个protocol接口,dubbo提供了若干该接口的实现。之后

meta-inf中添加一个配置文件,关联两者。


dubbo杂记-关于扩展点自适应_第1张图片

   图1-1 protocol接口类图


dubbo杂记-关于扩展点自适应_第2张图片

图1-2 配置文件


dubbo定义了ExtensionLoader用于处理扩展点。

ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Container.class);//加载扩展点

进入getExtensionLoader方法中:

    @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 interface!");
        }
        if (!withExtensionAnnotation(type)) {
            throw new IllegalArgumentException("Extension type(" + type +
                    ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
        }

        ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
        if (loader == null) {
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
            loader = (ExtensionLoader) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }
new ExtensionLoader(type)进去:
private ExtensionLoader(Class type) {
        this.type = type;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }
getAdaptiveExtension:
public T getAdaptiveExtension() {
        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;
    }
createAdaptiveExtension方法:
@SuppressWarnings("unchecked")
    private T createAdaptiveExtension() {
        try {
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);
        }
    }

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

   
getExtensionClasses方法从配置文件中获取扩展点全限定名,以classloader载入,构建扩展点class的对象。

接口能够自动适配的原理在getAdaptiveExtensionClass方法中。

getAdaptiveExtensionClass方法返回的是一个用javassit技术动态创建的类:

public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol


该类实现了接口的方法(动态生成的):

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);
	}
注意标红这里,以Protocol为键找到Protocol名下的诸多扩展点,然后根据传入的URL对象中的变量为键找到真正的实现,

然后调用方法。


这就是扩展点自适应的原理。









你可能感兴趣的:(dubbo)