你知道在Java 中常被提的 SPI 到底是什么吗?

谈谈SPI (Serial Peripheral Interface,串行外设接口) 今天我们来一起聊聊谈谈SPI (Serial Peripheral Interface,串行外设接口); 什么是SPI SPI (Serial Peripheral Interface,串行外设接口)是Motorola 公司推出的一 种同步串行接口技术,是一种高速的,全双工,同步的通信总线; 它以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,需要至少4根线,事实上3根... 阅读详情

Java 程序员在日常工作中经常会听到 SPI,而且很多框架都使用了 SPI 的技术,那么问题来了,到底什么是 SPI 呢?今天小编就带大家好好了解一下 SPI。

SPI 概念

SPI 全称是 Service Provider Interface,是一种 JDK 内置的动态加载实现扩展点的机制,通过 SPI 技术我们可以动态获取接口的实现类,不用自己来创建。

这里提到了接口和实现类,那么 SPI 技术上具体有哪些技术细节呢?

  1. 接口:需要有一个功能接口;

  2. 实现类:接口只是规范,具体的执行需要有实现类才行,所以不可缺少的需要有实现类;

  3. 配置文件:要实现 SPI 机制,必须有一个与接口同名的文件存放于类路径下面的 META-INF/services 文件夹中,并且文件中的每一行的内容都是一个实现类的全路径;

  4. 类加载器 ServiceLoader:JDK 内置的一个类加载器,用于加载配置文件中的实现类;

举个栗子

上面说了 SPI 的几个概念,接下来小编就通过一个栗子来带大家感受一下具体的用法。

第一步

创建一个接口,这里我们创建一个解压缩的接口,其中定义了压缩和解压的两个方法。

package com.example.demo.spi; /** * <br> * <b>Function:</b><br> * <b>Author:</b>@author ziyou<br> * <b>Date:</b>2022-10-08 21:31<br> * <b>Desc:</b>无<br> */ public interface Compresser { byte[] compress(byte[] bytes); byte[] decompress(byte[] bytes); } 复制代码

第二步

再写两个对应的实现类,分别是 GzipCompresser.java 和 WinRarCompresser.java 代码如下

package com.example.demo.spi.impl; import com.example.demo.spi.Compresser; import java.nio.charset.StandardCharsets; /** * <br> * <b>Function:</b><br> * <b>Author:</b>@author ziyou<br> * <b>Date:</b>2022-10-08 21:33<br> * <b>Desc:</b>无<br> */ public class GzipCompresser implements Compresser { @Override public byte[] compress(byte[] bytes) { return"compress by Gzip".getBytes(StandardCharsets.UTF_8); } @Override public byte[] decompress(byte[] bytes) { return "decompress by Gzip".getBytes(StandardCharsets.UTF_8); } } 复制代码
package com.example.demo.spi.impl; import com.example.demo.spi.Compresser; import java.nio.charset.StandardCharsets; /** * <br> * <b>Function:</b><br> * <b>Author:</b>@author ziyou<br> * <b>Date:</b>2022-10-08 21:33<br> * <b>Desc:</b>无<br> */ public class WinRarCompresser implements Compresser { @Override public byte[] compress(byte[] bytes) { return "compress by WinRar".getBytes(StandardCharsets.UTF_8); } @Override public byte[] decompress(byte[] bytes) { return "decompress by WinRar".getBytes(StandardCharsets.UTF_8); } } 复制代码

第三步

创建配置文件,我们接着在 resources 目录下创建一个名为 META-INF/services 的文件夹,在其中创建一个名为 com.example.demo.spi.Compresser 的文件,其中的内容如下:

com.example.demo.spi.impl.WinRarCompresser com.example.demo.spi.impl.GzipCompresser 复制代码

注意该文件的名称必须是接口的全路径,文件里面的内容每一行都是一个实现类的全路径,多个实现类就写在多行里面,效果如下。

第四步

有了上面的接口,实现类和配置文件,接下来我们就可以使用 ServiceLoader 动态加载实现类,来实现 SPI 技术了,如下所示:

package com.example.demo; import com.example.demo.spi.Compresser; import java.nio.charset.StandardCharsets; import java.util.ServiceLoader; public class TestSPI { public static void main(String[] args) { ServiceLoader<Compresser> compressers = ServiceLoader.load(Compresser.class); for (Compresser compresser : compressers) { System.out.println(compresser.getClass()); } } } 复制代码

运行的结果如下

可以看到我们正常的获取到了接口的实现类,并且可以直接使用实现类的解压缩方法。

原理

知道了如何使用 SPI 接下来我们来研究一下是如何实现的,通过上面的测试我们可以看到,核心的逻辑是 ServiceLoader.load() 方法,这个方法有点类似于 Spring 中的根据接口获取所有实现类一样。

点开 ServiceLoader 我们可以看到有一个常量 PREFIX,如下所示,这也是为什么我们必须在这个路径下面创建配置文件,因为 JDK 代码里面会从这个路径里面去读取我们的文件。

同时又因为在读取文件的时候使用了 class 的路径名称,因为我们使用 load 方法的时候只会传递一个 class,所以我们的文件名也必须是接口的全路径。

通过 load 方法我们可以看到底层构造了一个 java.util.ServiceLoader.LazyIterator 迭代器。

在迭代器中的 parse 方法中,就获取了配置文件中的实现类名称集合,然后在通过反射创建出具体的实现类对象存放到 LinkedHashMap<String,S> providers = new LinkedHashMap<>(); 中。

常用的框架

SPI 技术的使用非常广泛,比如在 Dubble,不过 Dubble 中的 SPI 有经过改造的,还有我们很常见的数据库的驱动中也使用了 SPI,感兴趣的小伙伴可以去翻翻看,还有 SLF4J 用来加载不同提供商的日志实现类以及 Spring 框架等。

优缺点

前面介绍了 SPI 的原理和使用,那 SPI 有什么优缺点呢?

优点

优点当然是解耦,服务方只要定义好接口规范就好了,具体的实现可以由不同的 Jar 进行实现,只要按照规范实现功能就可以被直接拿来使用,在某些场合会被进行热插拔使用,实现了解耦的功能。

缺点

一个很明显的缺点那就是做不到按需加载,通过源码我们看到了是会将所有的实现类都进行创建的,这种做法会降低性能,如果某些实现类实现很耗时了话将影响加载时间。同时实现类的命名也没有规范,让使用者不方便引用。

Arduino Nano + MCP3422A0 ADC 毫欧表:3档分辨率(0.1mΩ-1.3kΩ)开尔文连接实测 本文详细介绍了如何使用Arduino Nano与MCP3422A0 ADC构建高精度毫欧表,采用四线制开尔文连接和三档量程设计,实现0.1mΩ-1.3kΩ的精确测量。通过精密恒流源和18位ADC技术,结合智能量程切换和数字滤波算法,显著提升测量精度和稳定性,适用于电子维修、PCB测试等场景。 阅读详情

相关推荐

【FPGA】定点数运算中的位宽优化与截取策略

本文深入探讨了FPGA定点数运算中的核心挑战——数据位宽优化与截取策略。针对定点数在加法、乘法等运算中位宽膨胀的问题,文章详细分析了位宽变化规律,并对比了直接截断、四舍五入和收敛舍入三大截取策略的优缺点及硬件实现方法。通过实战指南与避坑经验,旨在帮助开发者在保证计算精度的同时,高效利用FPGA资源,实现性能与面积的平衡。

weixin_29181861的博客 118

全面解析 SPI 通信协议

SPI 的优点在于它有着比 I2C 更高的吞吐量,不被最大时钟速度所限制,可实现潜在的高速、极为简单的硬件接口,外围电路使用的上拉电阻是比 I2C 协议更少的,这意味着它具有比I2C的功耗更低、从机的时钟来源来自主机设备,无需新增精密振荡器、从机不需要唯一的地址、相对于并行接口而言,使用的引脚数目大大减少等优点。从图6可以看出,随着从机数量的增加,来自主机的片选线的数量也增加。此模式下的时钟相位为1,表示数据在下降沿采样(由橙色虚线显示),并且数据在时钟信号的上升沿移出(由蓝色虚线显示)。

jk_101的博客 2654

飞书云文档API实战:从权限申请到自动化操作

本文详细介绍了飞书云文档API的实战应用,从权限申请到自动化操作。内容涵盖如何创建应用、获取关键API权限、理解并使用Tenant Access Token,并通过Python代码示例演示了读取和写入飞书表格数据的具体方法,旨在帮助开发者和业务人员实现文档数据处理的自动化,提升工作效率。

weixin_28318011的博客 1943

SPI是什么以及特点、协议、使用方法

SPI是什么以及特点、协议、使用方法

hxw123aaa的博客 1579

360可视门铃双摄版数据恢复实战:BIN文件解析与视频重组

本文详细解析了360可视门铃双摄版BIN文件的数据恢复过程,包括文件结构分析、双摄像头数据存储机制及视频重组技术。通过Python开发环境和FFmpeg工具链,成功实现了H.265视频流的解析与重组,为智能家居设备数据恢复提供了实用解决方案。

weixin_29196891的博客 916

Unity URP项目里Post Processing死活没效果?别急,这5个坑我帮你踩过了

本文详细解析了Unity URP项目中Post Processing效果不显示的5个常见问题及解决方案,包括管线配置、Volume设置、摄像机选项、Layer冲突和Shader兼容性。通过专业排查步骤和实用代码片段,帮助开发者快速定位并修复后处理效果失效问题,提升项目开发效率。

weixin_28693309的博客 234

SPI技术理解及应用

一、什么是SPI ? SPI 全称:Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。 为了实现在模块装配的时候不用在程序里动态指明,这就需要一种服务发现机制。java spi就是提供这样的一个机制:为某个接口寻找服务实现的机制。这有点类似IOC的

卓尔货币的博客 3843

Marvell车载以太网交换机芯片88Q5050

Marvell推出了四款车载用交换机芯片,88Q5050,88Q5050, 88Q5072和88Q6113。其中88Q5030有5 Port用于通信,88Q5050有8 Port用于通信,5072与6113有11 Port用于通信。由于项目中用到了88Q5050,所以本文中只涉及到88Q5050的内容。本文是对使用88Q5050的梳理和总结。

zhuwade的博客 2万+

SPI学习&实践

1.什么是SPI SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。SPI的作用就是为这些被扩展的API寻找服务实现。 2.SPI和API的使用场景 API (Application Programming Interface)在大多数情况下,都是实现方制定接口并完成对接口的实现,调用方仅仅依赖接口调用,且无权选择不同实现。从使用人员上来说,API 直接被应用开发人员使用。 ...

嘉树麻麻 326

RK3566开发板实战:YT8512C百兆网卡调试全记录(附DTS配置避坑指南)

本文详细记录了RK3566开发板上YT8512C百兆以太网卡的调试全过程,包括硬件信号检测、DTS配置优化及常见错误排查。特别针对DTS配置中的关键参数和避坑指南进行了深入解析,为开发者提供实用的调试技巧和经验分享。

weixin_29189381的博客 273

RIP协议

一、 Rip简介 早期在unix系统上使用,1988年才发布第一个rip协议标准“RFC1058”,是一种距离矢量(Distance-vector)协议。 1. 特点: 只关心跳数,下一跳,不关心整网拓扑。 基于传闻的路由协议。 2. 场景: 适用于规模小且可靠性要求低的网络环境,部署简单,因为其跳数限制,不适用于大型网络。 3. 工作原理: - 开启RIP发送RIP请求 - 接受请求发出响应...

ledrsnet的博客 8608

Java开发 你应该知道 Java SPI 机制吧

SPI 即 Service Provider Interface ,字面意思就是:“服务提供者的接口”,我的理解是:专门提供给服务提供者或者扩展框架功能的开发者去使用的一个接口。SPI 将服务接口和具体的服务实现分离开来,将服务调用方和服务实现者解耦,能够提升程序的扩展性、可维护性。修改或者替换服务实现并不需要修改调用方。很多框架都使用了 Java 的 SPI 机制,比如:Spring 框架、数据库加载驱动、日志接口、以及 Dubbo 的扩展实现等等。

zxyhj的博客 789

YOLO26改进策略【YOLO和Mamba】| CVPR 2025:EfficientViM 压缩隐藏状态空间进行通道混合、单头设计减少内存操作,提升目标检测效率与精度

本文记录的是利用模块优化的目标检测网络模型。EfficientViM Block(基于隐藏状态混合器的状态空间对偶性模块) 的设计旨在,提升特征提取效率,同时兼顾全局依赖捕捉与局部细节保留。本文将深入研究的原理,并将其应用到中,通过重构特征提取流程、减少内存绑定操作、融合多阶段特征,增强模型在资源受限环境下的检测性能与速度。EfficientViM: Efficient Vision Mamba with Hidden State Mixer based State Space DualityEfficie

Limiiiing的博客 402

Dubbo - Dubbo的SPI机制

SPI是什么? SPI全称service provider interface,比如你有一个接口,现在这个接口有三个实现类,那么在系统运行的时候对这个接口到底选择哪个实现类呢?这就需要SPI了,需要根据指定的配置或者默认的配置,去找到对应的实现类加载进来,然后用这个实现类的实例对象。 举个例子: 你有一个接口A,A1/A2/A3分别是接口A的不同实现,你通过配置接口A = 实现类A2,那么系统在...

yang的博客 3万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java SPI机制简介,及dubbo SPI

转自:https://www.jianshu.com/p/46aa69643c97 SPI 简介 SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一种动态替换发现的机制, 举个例子来说, 有个接口,想运行时动态的给它添加实现,你只需要添加一个实现, 而后,把新加的实现,描...

潘建南的博客 3026

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

java中spi是什么_Java中的SPI

SPI是service provider interface的简写。本篇文章就讲解下SPI是做什么用的,以及怎么来使用。SPI这个东西还是非常好用的。SPI是什么SPI主要解决的还是耦合问题。我们知道面向接口编程是很好的编程方式,Java中会提前定义一些规范,一些接口,而接口的实现可以由第三方实现,只要其遵循接口实现规范即可。比如大家比较熟悉的JDBC就是这样的。提到SPI一般不得不提下类加载器C...

weixin_30568317的博客 5182

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Java SPI + Dubbo SPI

1. 什么是SPI SPI全称Service Provider Interface,服务提供接口,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。 2. API和SPI API (Application Programming Interface)叫应用程序接口,是有实现方制定接口并完成对接口的实现,调用方仅仅依赖接口调用,且无权选择不同实现。 从使用人员上来说,API 直接被应用开发人员使用。 SPI (Servic

水月青花 595

SPI机制是什么?

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

IT蜗牛的专栏 1万+

你知道SPI的原理以及实现?

是JDK内置的一种服务提供发现机制,可以用来启用框架扩展和替换组件,主要是被框架的开发人员使用,比如 java.sql.Driver 接口,其他不同厂商可以针对同一接口做出不同的实现,MySQL 和 PostgreSQL 都有不同的实现提供给用户,而Java的SPI机制可以为某个接口寻找服务实现。Java中SPI机制主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要,其核心思想就是解耦。Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。

weixin_50999696的博客 805

java实践SPI机制及浅析源码

1.概念 正式步入今天的核心内容之前,溪源先给大家介绍一下关于SPI机制的相关概念。 SPI即Service Provider Interface,属于JDK内置的一种动态的服务提供发现机制,可以理解为运行时动态加载接口的实现类。更甚至,大家可以将SPI机制与设计模式中的策略模式建立联系。 SPI机制: 从上图中理解SPI机制:标准化接口+策略模式+配置文件; SPI机制核心思想:系统设计的各个抽象,往往有很多不同的实现方案,在面向的对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬

增量星球 4085

关于SPI机制,你想知道的都在这里

什么是SPI SPI 是一种服务接口扩展的机制,全名service provider interface。通常由JDK定义接口,第三方做接口的实现,它的核心类是java.util.ServiceLoader。 SPI出现的背景 目的是将服务的定义与服务实现分离以达到解耦,从而提升程序可扩展性的机制。当我们开发一套框架、一套机制或者一套API的时候,如果需要第三方的服务支持(接口实现或...

sokia007的专栏 1205

java spi与dubbo spi区别

转自:https://www.jianshu.com/p/46aa69643c97 SPI 简介 SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一种动态替换发现的机制, 举个例子来说, 有个接口,想运行时动态的给它添加实现,你只需要添加一个实现, 而后,把新加的实现,描述给JDK知道就行啦(通过改一个文本文件即可)公司内部,目前Dubbo框架就基于SPI机制提供扩展功能。 简.

最爱奶油花生 333

Java SPI服务发现及Dubbo和Spring中SPI的应用

一、SPI简介 SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一种动态替换发现的机制, 举个例子来说, 有个接口,想运行时动态的给它添加实现,你只需要添加一个实现,而后,把新加的实现,描述给JDK知道就行啦(通过改一个文本文件即可)我们经常遇到的就是java.sql.Driver接口,其他不同厂商可以针对同一接口做出不同的实现,mysql和postgresql都有不同的实现提供给用户

山楂小王的博客 1995

【Java的SPI与SpringBoot自动配置】

SPI(Service Provide Interface)是一种扩展机制, 通常是为开发人员提供的, 实现可插拔式的扩展实现。java 6开始引入SPI, 主要基于ClassLoad发现并加载服务。主要有三大组件。

weixin_44541808的博客 1315

谈谈java中的SPI是什么

这是这个接口的具体方法,我们都知道数据库必须有Driver驱动,但是市面上的数据库种类繁多,比如有Mysql,Oracle,Druid等等,所以不同的数据库就需要利用JDK包下的这个Driver接口去实现自己各自的Driver实现类。其实这就是SPI,那么我们如果项目中有很多依赖,都实现了这个Driver接口,我们还可以在运行时,通过某种加载器(ServiceLoader,待会后面会讲)实现灵活的切换,而不用去显示的通过注解去注入不同的实现类。我们看看Mysql是如何去实现这个Driver接口的。

weixin_44826783的博客 881

Java之——深入理解SPI

SPI的概念 SPI在Java中的全称为Service Provider Interface,是JDK内置的一种服务提供发现机制,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。 JAVA SPI = 基于接口的编程+策略模式+配置文件 的动态加载机制 SPI的使用场景 Java是一种面向对象语言,虽然Java8开始支持函数式编程和Stream,但是...

冰河的专栏 1891
上一篇: 带你快速概览MySQL 整体架构
下一篇: 你知道MySQL锁,到底在锁什么吗?
Java_LingFeng
博客等级 码龄4年 505粉丝 259原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值