Spring Cloud Alibaba 教程 | Dubbo(三):ExtensionLoader加载过程

ExtensionLoader

通过前面文章的介绍我们已经知道通过ExtensionLoader可以获取到扩展接口实例对象,并且一个扩展接口对应着一个ExtensionLoader实例对象。ExtensionLoader是Dubbo SPI的实现核心,所以我们需要深入到源码研究它。在这里插入图片描述

ExtensionLoader的缓存数据

ExtensionLoader存放在dubbo-common模块,它加载扩展接口快速的原因就是因为它使用了很多的缓存数据,并且以成员变量形式包含在类结构中,可以将这些缓存数据分为两大类:全局缓存(静态变量)和私有缓存(私有变量)。

全局缓存

    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*");

    private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();

    private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();

SERVICES_DIRECTORY、DUBBO_DIRECTORY和DUBBO_INTERNAL_DIRECTORY这三个属性表示的是Dubbo在初始化加载扩展实现类的时候扫描的扩展配置文件位置,在Dubbo框架中实际上只使用到了DUBBO_INTERNAL_DIRECTORY这个目录位置META-INF/dubbo/internal。

EXTENSION_LOADERS是一个Map类型的静态变量,用来缓存所有扩展接口和对应的ExtensionLoader实例对象。
EXTENSION_INSTANCES也是一个Map类型的静态变量,用来缓存所有普通扩展实现类和对应的实例对象。

私有缓存

    private final Class<?> type;

    private final ExtensionFactory objectFactory;

    private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();

    private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();

    private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
    private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
    private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
    private volatile Class<?> cachedAdaptiveClass = null;
    private String cachedDefaultName;
    private volatile Throwable createAdaptiveInstanceError;

    private Set<Class<?>> cachedWrapperClasses;

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

type表示当前ExtensionLoader实例对象对应的扩展接口类型。
objectFactory主要用来实现Dubbo SPI的IOC特性。
cachedNames用于缓存普通扩展实现类和name的对应关系,和扩展配置文件中的配置key=value对应。
cachedClasses的内容和cachedNames相同,将cachedNames键值对调换即可得到cachedClasses。
cachedInstances存储扩展名称和扩展类对象的对应关系。如何该扩展接口包含有包装扩展类,那么扩展类对象将存储包装扩展类对象。
cachedAdaptiveInstance和cachedAdaptiveClass分别存储扩展接口的自适应扩展类对象和Class。
cachedDefaultName存储该扩展接口的默认扩展实现类,对应注解@SPI的value值。

ExtensionLoader加载过程

通过执行ExtensionLoader.getExtensionLoader(XXX.class)可以获取到扩展接口对应的ExtensionLoader实例对象,下面图是ExtensionLoader加载流程图:
在这里插入图片描述

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
	......//省略代码
    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;
}

断点执行上篇文章的例子,进入到getExtensionLoader()方法,type为PrintService.class,首先是通过EXTENSION_LOADERS获取扩展接口对应的ExtensionLoader对象,如果为空则new一个ExtensionLoader对象,并且缓存起来之后赋值给loader再返回。

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

实例化ExtensionLoader过程只处理type和objectFactory,type表示当前扩展接口类型,objectFactory是一个ExtensionFactory类型变量,当type不是ExtensionFactory.class时通过ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()赋值给objectFactory,ExtensionFactory同样是一个扩展接口:

@SPI
public interface ExtensionFactory {
    <T> T getExtension(Class<T> type, String name);
}

那么又会进入了getExtensionLoader()方法,此时type为ExtensionFactory.class,EXTENSION_LOADERS也不存在缓存实例,同样需要创建ExtensionLoader实例,只不过此时的type变成了ExtensionFactory.class,所以objectFactory直接赋值null。

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;

执行完new ExtensionLoader(ExtensionFactory.class)之后,存放缓存里面返回。这样就可以获取到了ExtensionFactory对应的ExtensionLoader对象,获取到ExtensionLoader之后执行getAdaptiveExtension()方法即:
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()获取到ExtensionFactory的自适应扩展类AdaptiveExtensionFactory实例。
在这里插入图片描述
objectFactory赋值之后,PrintService.class类型的ExtensionLoader就创建完成了,紧接着赋值给缓存EXTENSION_LOADERS,最后将实例loader返回,这样整个ExtensionLoader的加载过程就完成了。

后面文章会陆续对ExtensionFactory类和getAdaptiveExtension()方法进行详细解析。

关注公众号了解更多原创博文

Alt

发布了122 篇原创文章 · 获赞 127 · 访问量 93万+

猜你喜欢

转载自blog.csdn.net/u010739551/article/details/104188213