spi

dubbo spi 通过loader加载class,然后获取对应的实例,配置文件名为对应接口名,里面内容为中key:name,value:实现类

ExtensionLoader class加载器

内部静态属性

  • 三个目录

    • SERVICES_DIRECTORY: META-INF/services/

    • DUBBO_DIRECTORY: META-INF/dubbo/

    • DUBBO_INTERNAL_DIRECTORY: DUBBO_DIRECTORY+internal

  • NAME_SEPARATOR: 正则表达式,拆分名字使用(\\s*[,]+\\s*)

  • EXTENSION_LOADERS: k:class,v:ExtensionLoader

  • EXTENSION_INSTANCES: k:class,v:Object

比较重要内部属性

  • type: loader对应的类型,必定为interface

  • objectFacotry: ExtensionFactory 工厂类

  • cachedNames: k:class,v:String

  • cachedClasses: Hold<Map<String,class>> ,配置文件中对应k:v结构

  • cachedActives: k:String,v:Object

  • cachedAdaptiveClass @Adaptive修饰的实现类,最多一个

  • strategies: LoadingStrategy[]

    • DUBBO_INTERNAL_STRATEGY

    • DUBBO_STRATEGY

    • SERVICES_STRATEGY

构造函数

   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 an interface!");
        }
        if (!withExtensionAnnotation(type)) {
            throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
        }
    
        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;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

程序通过ExtensionLoader.getExtensLoader(type) 获取loader,由EXTENSION_LOADERS持有

比较常用的方法getAdaptiveExtension,getExtension(name)

getExtensionClasses方法,加载class

  • 然后调用loadExtensionClasses

    • cacheDefaultExtensionName 通过spi注解获取

    • 然后迭代strategies

      • loadDirectory

        • 利用classLoader加载对应接口文件

        • 路径为前面三个参数+type接口名

      • findResource

      • loadResource

      • loadClass

        • 判断class是否有Adaptive注解,是就cacheAdaptiveClass

        • 是否为wrapclass,是就cacheWrapClass

        • 核心功能就是一段saveInExtensionClass,其他都是兜底操作(构造器等),返回之后存入cachedClass

      • 获取classMap,文件中的kv结构

objectFactory.getExtension

  • objectFactory通过构造loader的时候通过getExtension(Factory)获取的

  • objectFactory 实际就是AdaptiveExtensionFactory

  • 构造这factory的时候,会获取实现的子类,并加入到集合中

  • getExtension

    • 迭代内部factory集合,调用getExtension

  • 内置spring和spi factory

    • spiFactory

      • 判断type是否为接口,判断接口是否被SPI注释

      • 通过后,并获取supportedExtensions,判断是否为空

      • 空返回null,不空返回对应type的adaptiveExtension

injectExtension实例注入

  • 迭代class的methods

    • 方法没有set方法就跳过

    • 有DisableInject也跳过

    • 第一个参数为基本类型,跳过

    • subString name 利用objectFactory.getExtension(class,name)获取实例

    • 注入到对应调用的Object中

Loader 两个核心方法

getExtension()

  • 一个holder缓存

  • 实例由createExtension方法创建

    • getExtensionClasses 加载资源,根据传入的key获取class

    • 创建实例,并通过injectExtension注入

    • 通过wrap包装实例,通过wrap构造器注入

    • 调用init方法

  • 返回实例

getAdaptiveExtension 获取Adaptive修饰的实现类

  • 抛开缓存的get和set方法

  • 进入createAdaptiveExtension方法

    • getAdaptiveExtension调用

    • 会发现内部调用getExtensionClasses资源加载类

    • 判断cacheAdpativeClass是否存在,存在就返回

      • 不存在,调用createAdaptiveExtensionClass根据type生成class

        • 如果方法中全部没有@Adaptive修饰的方法就会报错

        • 针对无修饰的方法会包装为扔出异常

        • 有修饰的进入生成内容环节

          • 检查参数是否存在URL类型

            • 存在,就生成检测URL参数是否为空的判断

            • 不存在,就从参数里面寻找getUrl方法获取URL类型

          • 剩下的生成内容比较简单,就不解释了

            • 主要功能获取Adpative注解上的value

            • 将方法拦截,从url中获取这个value为key对应的值

            • 并通过这个值通过getExtension 来动态获取对应的实例

            • 并调用对应实例的对应方法来达到动态代理效果

    • 实例化class

    • 属性注入

两个方法差异就是getExtension 会被wrap包装,adaptive动态编译class,内部通过extension获取实现的实例方法,没有就用默认值

Last updated