Seata之使用SPI实现配置加载的流程分析

前言

SPI( Service Provider Interface ) 机制这里不再赘述,详解出门右拐百度。

概括一句:定义接口功能,ClassLoader加载各类实现,以达到解耦、功能插拔的目的。 "基于接口的编程+策略模式+配置文件"

源码版本:1.4.2

由于ServiceLoader非线程安全(改篇讲),所以Seata的具体实现略不同

关键类

加载时机

通过全局搜索registry相关的类,找到加载操作的入口

静态方法加载registry


单例懒加载config


registry关联模块

ConfigurationFactory

ConfigurationFactory类通过静态代码块初始化变量CURRENT_FILE_INSTANCE

1、TC模块没有提供ExtConfigurationProvider的实现,因此返回FileConfiguration对象

2、Client模块有提供实现

主要作用是对生成的FileConfiguration对象添加方法拦截器,优先在bean内取配置参数


针对1、进行分析

传入registry文件名进行加载

形式类似future 可参考https://www.jianshu.com/p/e4363c574a1d 中future相关内容

image.png

config关联模块

ConfigurationFactory

这里采用饱汉单例模式

通过静态代码加载的配置项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获得实例化对象

你可能感兴趣的:(Seata之使用SPI实现配置加载的流程分析)