探索SpringBoot和Seata中的SPI机制实现

2023年 9月 7日 43.8k 0

本文章主要想了解一下SpringBoot,Seata组件中都是怎么使用SPI功能。如何调用SPI的接口实现类,能够提供哪些便利。

SPI (Service Provider Interface) -- 接口服务发现机制

Spring SPI

SpringBoot中最方便的功能莫过于自动配置功能,只需要集成一个Starter的jar包。基本不需要配置就可以实现数据库调用,远程调用,服务配置,服务发现等功能。Spring其实也是使用自己实现的SPI机制来进行的初始化加载并自动配置。

源码解析

Spring的加载都是通过调用SpringApplication.run来进行处理的。追踪一下这个注解,通过run方法可以很容易找到入口操作的地方。

这里就是部分的SPI入口,可以得知是加载了两个接口实现类,分别为ApplicationContextInitializer(应用上下文初始化类),ApplicationListener(应用监听类)

分为两步,第一步获取所有需要加载的SPI的全限定名称(使用Set来进行去重)。第二步利用BeanUtils.instantiateClass方法实例化这些对象。

获取需要加载的类

追踪后重点看一下这个箭头这里加载的路径,从资源路径加载和从系统路径加载。路径值为

这里就可以得到所有的SPI类都会放到上述路径中供spring加载。这里其实可以延伸一个问题,刚才只是加载了两个接口的类,Spring也实现其他接口的类。上面可以看到有一个8 usages,这里就可以知道调用的地方其实很多,对应其他的SPI实现接口类的加载。

ApplicationContextInitializer 应用上下文初始化类
ApplicationListener 应用监听类
SpringApplicationRunListener Spring应用执行监听
EnableAutoConfiguration(注解) 大部分自动配置类(invokeBeanFactoryPostProcessors(beanFactory);)
AutoConfigurationImportFilter 自动配置过滤类
AutoConfigurationImportListener 自动配置监听类
EnvironmentPostProcessor 环境变量执行器类
PropertySourceLoader 属性加载器

加粗的是比较常用的接口加载类,当需要使用对应功能时,直接在自己的Jar包中实现对应的接口,并配置到META-INF/spring.factories中即可。spring就可以读到对应的配置了。

常见用例

打开Mybatis Starter中的META-INF/spring.factories,可以看到

这里有一个概念需要强化一下,类上面添加了注解Configuration的类就不是一个普通的spring bean,具备了一定的配置功能。由ConfigurationClassParser中的parse方法来进行处理。类似于以前spring的一个xml文件,可以加载很多的bean。查看mybatis的配置类可以知道mybatis初始化了sqlSessionFactory,sqlSessionTemplate,spring相应的会自动配置这些bean到容器中。

Seata SPI

照例打开META-INF文件可以看到

在services文件夹下有多个文件,文件名称代表接口名称,文件内容是代表接口的多个实现。搜索全局代码后找到入口类时EnhancedServiceLoader(增强服务加载类)。核心的逻辑在内部类InnerEnhancedServiceLoader中。相应的也是有缓存机制,如果已经加载的类直接后去,SEATA的这个SPI使用静态方法实现,比较容易接入系统。

接着往下找,加载路径类的逻辑写在findAllExtensionDefinition中,分别加载了META-INF/servicesMETA-INF/seata中的实现类。代码里面可以找到很多参照spring的逻辑,加载的类也分为SINGLETONPROTOTYPE,同样也是采用DefinitionHolder来进行类的初始化等。

类的对象创建是在getExtensionInstance中实现,利用构造器创建的对象。整体看下来seata的SPI适配性更好,使用静态方法加载,且支持对象列表返回。

可以看到调用的地方是直接调用静态方法,传入想要的方法即可。

其实综合上面两种SPI机制,可以知道SPI是为扩展准备的,当需要适配不同类型的插件,且需要动态加载时。就可以采用SPI机制来进行加载自实现的接口实现类。

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论