dubbo源码,ExtensionLoader.strategies属性解析

首先看strategies 属性的定义:

private static volatile LoadingStrategy[] strategies = loadLoadingStrategies();

点进去看初始化方法:loadLoadingStrategies()

private static LoadingStrategy[] loadLoadingStrategies() {
    return java.util.stream.StreamSupport.stream(java.util.ServiceLoader.load(LoadingStrategy.class).spliterator(), false)
            .sorted()
            .toArray(LoadingStrategy[]::new);
}

加载过程解析
ServiceLoader.load方法,利用的是jdk自带的spi机制,加载 LoadingStrategy类的实现类,
jdk的spi机制约定了,接口实现类的描述文件存放位置为:META-INFO/services/,文件名称为接口的全限定名,即 org.apache.dubbo.common.extension.LoadingStrategy,文件内容如下:

org.apache.dubbo.common.extension.DubboInternalLoadingStrategy
org.apache.dubbo.common.extension.DubboLoadingStrategy
org.apache.dubbo.common.extension.ServicesLoadingStrategy

显然,LoadingStrategy接口有三种实现,因此,jdk的spi机制,会将这三个实现分别初始化,并以数组的方式填充到 strategies属性中,也就是说,不同的属性代表着不同的加载策略。

到这一步,strategies属性就加载完成了。那么,strategies字段在哪里使用呢?

我们再来看这一段代码:

private Map<String, Class<?>> loadExtensionClasses() {
    cacheDefaultExtensionName();

    Map<String, Class<?>> extensionClasses = new HashMap<>();

    for (LoadingStrategy strategy : strategies) {
        loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
        loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
    }

    return extensionClasses;
}

总结:strategies中的每一项,代表着不同的spi加载策略,每一种加载策略,都有相应的目录结构。因此dubbo通过遍历strategies,来读取某一个接口在所有策略下的所有实现类,并以k - v的方式缓存到extensionClasses中,但是到这一步,还仅仅读取了实现类的class对象,而没有进行初始化。后续使用实现类时,可以直接拿到class对象,而不需要再去读取文件了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。