前言
SPI( Service Provider Interface ) 机制这里不再赘述,详解出门右拐百度。
概括一句:定义接口功能,ClassLoader加载各类实现,以达到解耦、功能插拔的目的。 "基于接口的编程+策略模式+配置文件"
源码版本:1.4.2
由于ServiceLoader非线程安全(改篇讲),所以Seata的具体实现略不同
关键类
加载时机
通过全局搜索registry相关的类,找到加载操作的入口
静态方法加载registry
单例懒加载config
registry关联模块
ConfigurationFactory类通过静态代码块初始化变量CURRENT_FILE_INSTANCE
1、TC模块没有提供ExtConfigurationProvider的实现,因此返回FileConfiguration对象
2、Client模块有提供实现
主要作用是对生成的FileConfiguration对象添加方法拦截器,优先在bean内取配置参数
针对1、进行分析
传入registry文件名进行加载
形式类似future 可参考https://www.jianshu.com/p/e4363c574a1d 中future相关内容
config关联模块
这里采用饱汉单例模式
通过静态代码加载的配置项CURRENT_FILE_INSTANCE获取config对应的参数配置
这里加载的是file.conf文件配置
后面逻辑针对创建的Configuration对象,设置了代理,主要目的是在进程内存内缓存配置项(ConcurrentHashMap线程安全)
至此可得出ConfigurationFactory共存储了registry、config两类配置参数,即seata配置文件registry.conf
中registry根节点信息及对应config类型所对应的配置信息(例如:file.conf)
EnhancedServiceLoader
registry、config的配置信息,都是通过EnhancedServiceLoader.load加载的
由图可见分为两步 getServiceLoader、load
getServiceLoader
load
1、加载扩展类
2、存储类信息
3、初始化实例
加载扩展类
至此class包装成ExtensionDefinition对象存储在classToDefinitionMap、nameToDefinitionsMap
获取类信息
由于类已经加载并存储,紧接着进行实例化
在当前接口下查找默认实现类、在当前接口下通过name查找实现类
初始化实例
至此接口扩展的实现类,通过LoadLevel注解添加的信息,能够通过EnhancedServiceLoader获得实例化对象