Java SPI 浅析一二

SPI 三剑客:Java、Spring、Dubbo SPI 深度解析与实践​ 从 Java 原生 SPI 的 “基础通用”,到 Spring SPI 的 “生态适配”,再到 Dubbo SPI 的 “分布式增强”,三种 SPI 机制的演进,本质上是 “从满足通用需求到适配特定场景” 的过程:​Java SPI 是 “基石”,提供了最简洁的服务发现能力,适用于无框架依赖的轻量级场景;​Spring SPI 是 “生态增强”,将 SPI 与 IoC 深度结合,成为 Spring 生态扩展的标准方式;​。 阅读详情

Java SPI

SPI : Service Provider Interface 为某个接口寻找服务实现的机制。

1. 为何需要SPI

基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。

Usually API and SPI are separate. For example, in JDBC the Driver class is part of the SPI: If you simply want to use JDBC, you don’t need to use it directly, but everyone who implements a JDBC driver must implement that class.

2. 默认约定

当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。通过这个约定,就不需要把服务放在代码中了,通过模块被装配的时候就可以发现服务类了。

3. 使用案例

3.1 common-logging

common-logging apache最早提供的日志的门面接口。只有接口,没有实现。具体方案由各提供商实现, 发现日志提供商是通过扫描 META-INF/services/org.apache.commons.logging.LogFactory配置文件,来发现日志实现类。只要我们的日志实现里包含了这个文件,并在文件里指定了 LogFactory工厂接口的实现类即可。

3.2 Spring

在springboot的自动装配过程中,最终会加载META-INF/spring.factories文件,而加载的过程是由SpringFactoriesLoader加载的。从CLASSPATH下的每个Jar包中搜寻所有META-INF/spring.factories配置文件,然后将解析properties文件,找到指定名称的配置后返回。需要注意的是,其实这里不仅仅是会去ClassPath路径下查找,会扫描所有路径下的Jar包,只不过这个文件只会在Classpath下的jar包中。

3.3 JDBC

在JDBC4.0之前,我们开发有连接数据库的时候,通常会用Class.forName(“com.mysql.jdbc.Driver”)这句先加载数据库相关的驱动,然后再进行获取连接等的操作。而JDBC4.0之后不需要用Class.forName(“com.mysql.jdbc.Driver”)来加载驱动,直接获取连接就可以了,现在这种方式就是使用了Java的SPI扩展机制来实现。

  • JDBC接口定义
    首先在java中定义了接口java.sql.Driver,并没有具体的实现,具体的实现都是由不同厂商来提供的。

  • mysql实现
    在mysql的jar包中,可以找到META-INF/services目录,该目录下会有一个名字为java.sql.Driver的文件,文件内容是com.mysql.cj.jdbc.Driver,这里面的内容就是针对Java中定义的接口的实现。

  • postgresql实现
    同样在postgresql的jar包中,也可以找到同样的配置文件,文件内容是org.postgresql.Driver,这是postgresql对Java的java.sql.Driver的实现。

3.4 Eclipse插件

Eclipse使用OSGi作为插件系统的基础,动态添加新插件和停止现有插件,以动态的方式管理组件生命周期。 一般来说,插件的文件结构必须在指定目录下包含以下三个文件: META-INF/MANIFEST.MF: 项目基本配置信息,版本、名称、启动器等
build.properties: 项目的编译配置信息,包括,源代码路径、输出路径
plugin.xml:插件的操作配置信息,包含弹出菜单及点击菜单后对应的操作执行类等.

4. 自己用ServiceLoader实现SPI

定义一个接口和相关的实现类

public interface Save {
    void save(String message);
}

public class FileSaver implements Save{
    @Override
    public void save(String message) {
        System.out.println("saveit in file");
    }
}

public class DBSaver implements Save{
    @Override
    public void save(String message) {
        System.out.println("saveit in DB");
    }
}

在Resource目录下建目录 META-INF/services/ 和文件 com.spi.Save文件。注意文件名就是接口的全路径名称。
在这里插入图片描述
然后在文件内写明实现类。

com.spi.DBSaver
com.spi.FileSaver

这样子在Main里实现接口实现类的自动查找与实例化。

public class Main {
    public static void main(String[] args) {
        ServiceLoader<Save> load = ServiceLoader.load(Save.class);
        Iterator<Save> iterator = load.iterator();
        while (iterator.hasNext()){
            Save save = iterator.next();
            save.save("Hello");
        }
    }
}

运行结果:

saveit in DB
saveit in file

5. ServiceLoader源码

ServiceLoader类内的迭代器有一个LazyIterator,其中会根据文本加载类:
c = Class.forName(cn, false, loader);并且实例化:S p = service.cast(c.newInstance());。

  private class LazyIterator
        implements Iterator<S>
    {
  private S nextService() {
            if (!hasNextService())
                throw new NoSuchElementException();
            String cn = nextName;
            nextName = null;
            Class<?> c = null;
            try {
                c = Class.forName(cn, false, loader);
            } catch (ClassNotFoundException x) {
                fail(service,
                     "Provider " + cn + " not found");
            }
            if (!service.isAssignableFrom(c)) {
                fail(service,
                     "Provider " + cn  + " not a subtype");
            }
            try {
                S p = service.cast(c.newInstance());
                providers.put(cn, p);
                return p;
            } catch (Throwable x) {
                fail(service,
                     "Provider " + cn + " could not be instantiated",
                     x);
            }
            throw new Error();          // This cannot happen
        }
}

总结

SPI将装配的控制权移到了程序之外。
只要是能满足用户按照系统规则来自定义,并且可以注册到系统中的功能点,都带有着spi的思想。

java基础 系列在github上有一个开源项目,主要是本系列博客的demo代码。https://github.com/forestnlp/javabasic
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。

Java学习——MP3SPI介绍 MP3SPI 是一个基于 Java SPI 机制的扩展库,填补了 Java Sound API 不支持 MP3 格式的空白。它通过 MP3 解码器服务将压缩音频转换为 PCM 格式,使 AudioSystem 能处理 MP3 文件播放。依赖三个核心 JAR 文件,MP3SPI 提供了轻量级集成方案,支持格式转换与实时播放。相比 JLayer 和 JavaFX Media,MP3SPI 的优势在于无缝扩展 Java Sound API,适合需要灵活音频处理的场景,但功能仅限于 MP3 解码。适用于纯 Java 阅读详情

相关推荐

华为2288H-V5服务器做raid的详细步骤

操作步骤 服务器启动界面 按del键进入设置输入密码,2288H-v5默认密码是Admin@9000 移动光标选择device manager 驱动管理选择configurationutility 配置管理 选择main menu 主菜单 选择第一个 configuration management 配置管理 选择create virtual driver 创建虚拟驱动选择select RAID level 选择RAID等级选择level-5 选择select drivers 选择驱......

weixin_46041124的博客 1万+

了解 Eclipse 插件如何使用 OSGi

本文通过描述对 Eclipse 平台而言插件是什么,并跟踪从 Eclipse V2.1 到今天基于 OSGi 的实现中插件的发展,阐明了 Eclipse 与 OSGi 的关系。还解释了 OSGi manifest.mf 文件选项以及通过 Eclipse 提供的添加项。 清单 3. Manifest.mf Manifest-Version: 1.0 Bundle-Name: %name ...

Daogene 152

第18届全国大学生智能汽车竞赛四轮车开源讲解【2.5】-- 图像处理实战:从二值化到边缘检测的工程优化

本文深入讲解了第18届全国大学生智能汽车竞赛四轮车开源项目中图像处理的核心实战技术。文章聚焦于二值化与边缘检测两大关键环节,详细对比了大津法与索贝尔算子的工程应用与优化策略,并分享了遮光、偏振片等物理抗干扰技巧,旨在帮助参赛者构建稳定高效的图像预处理流水线,为赛道识别奠定坚实基础。

weixin_29279047的博客 100

一文理解Java中的SPI机制

SPI机制简介服务提供者接口(Service Provider Interface,简写为SPI)是JDK内置的一种服务提供发现机制。可以用来加载框架扩展和替换组件,主要是被框架的开发人员...

全菜工程师小辉的博客 1531

CANoe.Diva实战:基于CDD的UDS诊断自动化测试全流程解析

本文详细解析了使用CANoe.Diva进行基于CDD的UDS诊断自动化测试的全流程,包括环境搭建、CDD文件配置、测试范围设置、用例生成与验证、CANoe集成测试及报告分析。通过实战经验分享,帮助工程师快速掌握诊断自动化测试技巧,提升测试效率与质量。

weixin_29258297的博客 218

DPABI安装教程

DPABI是是中科院心理研究所严超赣老师团队开发的一款磁共振脑影像数据分析工具包。基于SPM,在安装DPABI之前需要安装好SPM,才能正常使用。SPM的安装方法见文matlab2021a版本条件下安装spm_kidllll的博客-优快云博客 1、下载安装包 下载地址:DPABI: a toolbox for Data Processing & Analysis for Brain Imaging | The R-fMRI Network 2、将下载好的dpabi文件夹移动到matl..

qq_42356925的博客 1万+

java spi基本demo

在项目的配置文件目录下/src/test/resources 创建/META-INF/services 在这个文件夹下创建com.demo.intf.SpiService文件 文件的内容com.demo.intf.impl.SpiServiceImpl 操作完成之后执行下面的测试代码public class PopTest { @Test public void test()

喜欢炒股的码农 709

Isaac Sim 车辆动力学:从参数调优到户外仿真的挑战与实战

本文深入探讨了Isaac Sim在车辆动力学仿真中的应用,从参数调优到户外场景模拟的实战经验。详细解析了悬架系统、轮胎物理模型等核心参数的设置技巧,并分享了应对户外仿真挑战的实用方案。通过Vehicle Wizard高级使用和传感器配置,帮助开发者高效完成车辆仿真与算法开发。

weixin_29192211的博客 404

Java的SPI机制与简单的示例

一、SPI机制 这里先说下SPI的一个概念,SPI英文为Service Provider Interface单从字面可以理解为Service提供者接口,正如从SPI的名字去理解SPI就是Service提供者接口;我对SPI的定义:提供给服务提供厂商与扩展框架功能的开发者使用的接口。 在我们日常开发的时候都是对问题进行抽象成Api然后就提供各种Api的实现,这些Api的实现都是封装与我们

z69183787的专栏 2874

日语五十音图速记攻略:从形象联想法到实战训练

语言学习中的记忆编码与条件反射构建是高效掌握基础的关键。其核心原理在于通过将抽象符号与具象图像、故事或已知概念关联,利用大脑对视觉和叙事信息的天然高记忆效率,从而降低认知负荷,加速识别与反应速度。这一方法的技术价值在于将机械重复转化为意义联结,显著提升长期记忆的牢固度与提取速度。在日语学习这一具体应用场景中,五十音图作为表音文字系统,正是实践这一记忆技术的绝佳对象。通过系统化的形象联想、分组对比(如平假名与片假名的对应关系)以及间隔重复的实战训练,学习者可以高效攻克这一入门难关,为后续的词汇、语法学习铺设坚

weixin_29032489的博客 378

Realsense D435i运行ORB-SLAM3

【代码】Realsense D435i运行ORB-SLAM3。

MAX_Hope的博客 2563

java实践SPI机制及浅析源码

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

增量星球 4082

【HALCON工业视觉应用探索】02. C# + Halcon铸件毛刺机器人打磨引导:点云处理从实验室到工业现场的全流程落地

摘要:铸件毛刺的自动化打磨是机械制造领域的重要难题,其随机性(高度0.1-3mm)和复杂工况导致人工打磨效率低(3分钟/件)、工伤率高。本文基于Halcon 24.11与.NET 6,构建了一套点云处理方案:通过线激光扫描仪获取三维点云,经预处理、毛刺检测、路径规划三大模块,引导机器人完成打磨。虚拟实验测试显示,对高度>1mm的毛刺检出率达100%,定位误差±0.08mm,但工业现场受油污、粉尘影响,性能降至检出率68-75%、处理时间>45秒。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1128

Java SPI详解

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

lukabruce的博客 1万+

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

浅析Java-SPI机制

Java SPI机制 SPI全称为Service Provider Interface(服务提供接口),是JDK内置的一种服务发现机制,是一种将服务接口与具体实现分离以达到解耦,大大提升了程序可扩展性的机制,引入服务提供者就是引入了spi接口的实现者,通过本地的注册发现获取到具体的实现类。 Java SPI实际上就是"基于接口的编程+策略模式+配置文件"组合实现的动态加载机制。 系统设计之初为了各个功能模块之间解耦,一般都是基于接口编程,模块之间不对实现类进行硬编码,一旦代码涉及到具体实现类的耦合,就违反了

wyg1973017714的博客 602

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【Java杂记】SPI机制:使用示例及原理浅析

1.SPI是什么 SPI全称Service Provider Interface,是 JDK 内置的一种服务提供发现机制,目前市面上有很多框架都是用它来做服务的扩展发现。简单来说,它是一种动态替换发现的机制。它可以用来启用框架扩展和替换组件。整体机制图如下: Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。 接口:调用方需要的服务 策略模式:多个提供方,会提供自己的接口实现 配置文件:提供方告知调用方,具体实现类在哪里,然后调用方去加载;本质上是一种通信方式 =

A minor 2033

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

java spi浅析

1. Java spi是什么 SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的接口,它可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。 2. 使用 定义spi接口 定义多态实现 按固定规范 即classpath:/META-INF/services目录下新建spi接口的全限定类名文件 文件内按行填写该spi接口用到的实现类 ServiceLoader.load(spiInterface.class) 使

快乐小咸鱼007的博客 536

Java的SPI机制

SPI是什么 SPI的英文名称是Service Provider Interface,是Java 内置的服务发现机制。 在开发过程中,将问题进抽象成API,可以为API提供各种实现。如果现在需要对API提供一种新的实现,我们可以不用修改原来的代码,直接生成新的Jar包,在包里提供API的新实现。通过Java的SPI机制,可以实现了框架的动态扩展,让第三方的实现能像插件一样嵌入到系统中。 Java的...

小白张的博客 1万+

【java】从java SPI机制到dubbo SPI机制(源码浅析)

(仔细读了源码画了流程图,对dubbo的SPI机制总算有了了解,期待以后继续的收获,痛并快乐着) java的SPI机制到底是什么? 简单实现一个java-SPI示例,其有什么不足? dubbo源码如何实现改进SPI,对SPI进行AOP、IOC、自适应、自激活? (dubbo为2.7.2版本) 目录 一、什么是SPI? 二、简单的SPI示例实现 三、Java SPI...

funyoo的博客 588

彻底理解SPI 机制 (Java SPI 、Spring SPI、Dubbo SPI)

1SPI 全称为,是一种服务发现机制。SPI 的本质是将的中,并由。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。

m0_50180963的博客 945

武汉小米 Java 岗位一二面校招面经

小米 Java 岗位的面试难度并不大,问题也较为常规,主要以技术八股文为主,手撕算法题基本来自 Leetcode 上的常见题目,整体难度适中。下面,分享一篇武汉小米 Java 岗位的校招面经(一二面核心问题整理,附带详细参考答案),大家可以感受一下具体的面试难度。

JavaGuide 1299

JAVA SPI机制深入详解

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

wangxuelei036的博客 1万+

Java SPI机制

SPI的全称是Service Provider Interface,中文名为服务提供者接口,是一种服务发现机制,基于JDK内置的动态加载实现扩展点的机制。

csdn_fanhehua的博客 3173

Java Spi以及Dubbo Spi

无

weixin_44716359的博客 1014
上一篇: Java反射浅析一二
下一篇: Java集合源码阅读之ArrayList和LinkedList
悟空学编程
博客等级 码龄12年 32粉丝 123原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值