SPI |


Java SPI

SPI 全称 Service Provider Interface,是 Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API 寻找服务实现。本质是通过基于接口的 编程+策略模式+配置文件 实现动态加载。可以实现 解耦 (接口和实现分离),提高框架的 可拓展性(第三方可以自己实现,达到插拔式的效果)。
我们来开发SPI看一下。
首先定义一个接口。
定义不同的实现类。
在指定目录(META-INF.services)下创建文件,(为什么是这个目录接下来会讲到)。
notion image
文件名是接口的全类名,文件内容是实现类的全类名。
编写测试单元测试。是通过ServiceLoader这个类实现的功能,接下来会详细讲解这个类的实现原理。
执行结果为
通过执行结果我们可以看出,HelloSpi接口的所有实现类都得到了调用,我们可以通过这种机制根据不同的业务场景实现拓展的效果。示例是通过ServiceLoader实现的,我们来看一下这个类。

ServiceLoader

ServiceLoader是一个简单的服务提供者加载工具。是JDK6引进的一个特性。
load方法是通过获取当前线程的 线程上下文类加载器 实例来加载的。Java应用运行的初始线程的上下文类加载器默认是系统类加载器。这里其实 破坏了双亲委派模型,因为Java应用收到类加载的请求时,按照双亲委派模型会向上请求父类加载器完成,这里并没有这么做(有些面试官会问到破坏双亲委派模型相关问题,简单了解)。
iterator.hasNext()主要是通过 hasNextService()来实现的,我们来看一下主要代码。
该方法会去加载 PREFIX 变量路径下的配置,PREFIX 是一个固定路径,这也就是我们为什么要在META-INF/services/下创建文件的原因。并根据 PREFIX 加上全类名获取到实现类所在的全路径。
notion image
Java中有许多我们常见的框架使用SPI机制的地方,JDBC,Dubbo,Logback等,Spring中也有使用。

Spring SPI

Spring SPI对 Java SPI 进行了封装增强。我们只需要在 META-INF/spring.factories 中配置接口实现类名,即可通过服务发现机制,在运行时加载接口的实现类。
我们将讲解 Java SPI 的例子通过Spring SPI来实现一下。
测试代码如下。
执行结果,与Java SPI执行结果一致。

Springboot利用Spring SPI开发starter

刚接触 Springboot 的时候引入一个个starter依赖,当时十分好奇这个东西,这一个个的starter就是通过Spring SPI来实现的。
我们也可以自己编写一个starter提供一些功能,传入公司的maven仓库,需要用到的项目就可以直接引入,减少项目对某些模块的代码硬侵入。
先来编写接口和实现。
spring.factories中内容。
pom.xml指定groupId,artifactId,version。
然后通过maven打包传入maven仓库。其他的Springboot项目就可以直接使用了。
Loading...
目录
文章列表
王小扬博客
产品
Think
Git
软件开发
计算机网络
CI
DB
设计
缓存
Docker
Node
操作系统
Java
大前端
Nestjs
其他
PHP