当前位置:网站首页>SPI机制是什么?
SPI机制是什么?
2022-08-03 02:03:00 【程序员超时空】
一、SPI机制是什么?
spi全称为 (Service Provider Interface),是JDK内置的一种服务提供发现机制。SPI是一种动态替换发现的机制,一种解耦非常优秀的思想。
spi的工作原理: 就是ClassPath路径下的META-INF/services文件夹中, 以接口的全限定名来命名文件名,文件里面写该接口的实现。然后再资源加载的方式,读取文件的内容(接口实现的全限定名), 然后再去加载类。
spi可以很灵活的让接口和实现分离, 让api提供者只提供接口, 第三方来实现。

优点:
- 使用Java SPI机制的优势是实现解耦,使得第三方服务模块的装配控制的逻辑与调用者的业务代码分离,而不是耦合在一起。应用程序可以根据实际业务情况启用框架扩展或替换框架组件。
缺点:
- 虽然ServiceLoader也算是使用的延迟加载,但是基本只能通过遍历全部获取,也就是接口的实现类全部加载并实例化一遍。如果你并不想用某些实现类,它也被加载并实例化了,这就造成了浪费。获取某个实现类的方式不够灵活,只能通过Iterator形式获取,不能根据某个参数来获取对应的实现类。
- 多个并发多线程使用ServiceLoader类的实例是不安全的。
二、SPI如何使用
那么现在有这样的场景:当我的项目里面有什么支付模块我就使用什么样的支付模块,比如说有支付宝支付模块就选择支付宝、有微信支付模块我就选择微信支付、同时有多个的时候,我默认选择第一个,此时我们就可以使用SPI,先看下如何使用。
1、创建META-INF/services文件夹,然后创建一个以Pay接口全限定名为名字的文件

2、在文件中编写想要实现哪个Pay的实现类(AliPay,WechatPay,BankCardPay),注意也要是全限定名。假如是是支付宝支付的模块,上面文件的内容:com.taolong.dubbo.spi.strategy.AliPay
3、获取Pay并调用
获取并调用的逻辑,我就修改下上面的策略模式中的Context的invokerStrategy方法,这里假设默认使用第一个
public void invokeStrategy(){
ServiceLoader<Pay> payServiceLoader = ServiceLoader.load(Pay.class);
Iterator<Pay> iterator = payServiceLoader.iterator();
if (iterator.hasNext()){
iterator.next().pay();
}
}
三、SPI的优秀实现案例
我们来看一个真实的使用上述SPI的例子—数据库驱动(Driver)。
我们知道,当我们的项目里面使用引用了mysql的驱动pom依赖时,我们的项目里面会自动选择使用mysql的驱动,我们甚至不需要手动去加载。我们来看看它的具体实现。
1、首先看一下java.sql.Driver的类,这里面也是相当于定义了一个规范
2、其次看mysql驱动包的META-INF/services文件夹下面有没有指定的文件

很熟悉,命名就是java.sql.Driver
3、打开文件查看一下文件内容

这里面就能看到我们的mysql的驱动了,到这里基本上就确认这也是使用SPI实现的,顺便说一下,现在为什么我们不需要使用Class.forName()去加载驱动了,这是因为DriverManager使用SPI的机制已经帮我们加载好了,我们来看看DriverManager的类
不管是文件名还是文件内容都是全限定名,所以通过反射很容易创建相应的类

在现有框架中的使用
其实了解SPI机制是因为最近看SpringBoot代码的时候发现的,我们知道在SprngBoot中好多的配置和实现都有默认的实现,我们只需要修改部分配置,比如数据库配置,我们只要在配置文件中写上对应的url,username,password就可以使用了。其实他这边用的就是SPI的方式实现的
不过Spring使用的只是和JDK中的原理相同而已。
JDK使用的工具类是ServiceLoader
Spring中使用的类是SpringFactoriesLoader,在 org.springframework.core.io.support包中
区别:
文件路径不同 spring配置放在 META-INF/spring.factories中
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦
边栏推荐
猜你喜欢

vsftp容器搭建+go开发web用户管理界面(更新于2022.02.23)

【云原生】灰度发布、蓝绿发布、滚动发布、灰度发布解释

【UE4】搭建局域网内VR直播 UE4.27

豆瓣评分9.3的好书,文末给大家抽奖送几本!

EasyGBS播放器优化:设备通道视频播放出现跳屏问题的修复

国标GB28181协议EasyGBS平台项目现场通知消息过多导致系统卡顿该如何解决?

The cornerstone of high concurrency: multithreading, daemon threading, thread safety, thread synchronization, mutual exclusion lock, all in one article!...

Summary of some interviews

JVM internal structure and various modules operation mechanism

FLIR E95 在8层楼看马路上行驶的CAR的热成像形态?
随机推荐
为什么要使用 playwright 做浏览器自动化测试?
国标GB28181协议EasyGBS平台项目现场通知消息过多导致系统卡顿该如何解决?
EasyGBS播放器优化:设备通道视频播放出现跳屏问题的修复
企业云成本管控,你真的做对了吗?
【Arduino】重生之Arduino 学僧(2)----Arduino语言
QWidget、QPushButton、
通过kubernetes可视化界面(rancher)安装kibana
面试题整理1
Kook机器人开发日志01
【云原生】阿里云ARMS业务实时监控
禁用token及无感知更新token功能实现
【云原生】灰度发布、蓝绿发布、滚动发布、灰度发布解释
选中按钮上色
List转Map的几种方式
”QSqlDatabasePrivate::removeDatabase: connection ‘test-connect‘ is still in use“数据库多次打开报错
ROS计算图——rqt_graph
实现统一账号登录,sonarqube集成ldap
常用工具链和虚拟环境-msys2与mingw
236. The binary tree in recent common ancestor
【Objective-C语言中的@property增强】