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
构造函数
程序通过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