Java SPI介绍

news2025/4/24 18:03:10

SPI

Java SPI : Service Provider Interface

是Java平台提供的一种机制,用于动态的加载和扩展功能的机制,它为框架和库提供了一种松耦合的扩展方式,核心是解耦。

例如JDBC驱动,日志框架,等应用,它为开发者提供了一种灵活的,可插拔的扩展机制,使得使用更加方便灵活,更改配置即可。

SPI整体机制图

请添加图片描述

SPI和API区别?

API 是用于定义和提供功能接口的一种方式;

而 SPI 是一种用于动态加载和扩展功能的机制。

SPI接口位于调用方包中:

接口位于调用方中,而实现在独立的包之中。

API接口位于实现方包中:

接口和实现均位于一个包中。

SPI 代码实现

  1. 先创建一个接口

    package com.junfeng.spi;
    
    public interface Logger {
        void log(String msg);
    }
    
    
  2. 实现接口

    console实现:

    package com.junfeng.spi;
    
    public class ConsoleLogger implements Logger {
        @Override
        public void log(String msg) {
            System.out.println("console sys logger:" + msg);
        }
    }
    
    

    file实现:

    package com.junfeng.spi;
    
    public class FileLogger implements Logger {
        @Override
        public void log(String msg) {
            System.out.println("file sys logger:" + msg);
        }
    }
    
  3. 配置

    创建配置文件:为每个提供者创建一个配置文件,指定提供者的实现类名。

    META-INF/services/ 目录下创建文件 com.junfeng.spi.Logger,其中 com.junfeng.spi.LoggerLogger 接口的完全限定名,内容如下:

    com.junfeng.spi.ConsoleLogger
    com.junfeng.spi.FileLogger
    
  4. 调用

    在这个示例中,ServiceLoader.load(Logger.class) 用于加载 Logger 接口的实现提供者,然后通过遍历加载的提供者,调用其 log 方法输出日志。

package com.junfeng.spi;

import java.util.ServiceLoader;

public class Test {

    public static void main(String[] args) {
        // 加载 Logger 接口的实现
        ServiceLoader<Logger> loggerLoader = ServiceLoader.load(Logger.class);
        // 遍历并使用实现提供者
        for (Logger logger : loggerLoader) {
            logger.log("hello");
        }
    }
}

原理

SPI 机制的底层原理是基于 Java 的标准类加载和反射机制。

有兴趣的看下Class.forName,里面使用到了反射方法Class.forName()加载类对象。

SPI优缺点

优点:

  1. 松耦合和可扩展性:SPI 机制可以实现插件化的架构,将接口和实现彻底解耦,使得框架和应用程序更易于扩展和维护。通过添加新的实现提供者,可以在不修改代码的情况下扩展功能。
  2. 动态加载和发现:SPI 允许在运行时动态加载实现提供者,使得框架能够根据配置文件自动发现和加载新的功能模块,从而实现了更大的灵活性。
  3. 无需修改源代码:使用 SPI,开发人员可以将接口和实现分开,避免了在框架源代码中引入大量的条件判断,使得框架更加清晰和可维护。
  4. 分离关注点:SPI 机制允许框架关注于核心功能,而将特定的实现细节留给实现提供者来处理,提高了代码的模块化和可理解性。

缺点:

  1. 没有版本管理:SPI 机制本身不提供强大的版本控制机制,当不同版本的提供者实现并存时,可能会导致不可预测的行为。
  2. 没有依赖管理:SPI 机制不具备管理依赖关系的能力,这意味着实现提供者在开发时需要确保依赖的库和版本是正确的。
  3. 不适用于复杂多实现场景:SPI 适用于一对一的接口和实现关系,当存在复杂的多实现关系时,可能需要更高级的机制来管理和调度实现。
  4. 运行时的性能开销:SPI 机制在运行时需要进行实现提供者的查找和加载,这会带来一些性能开销,尤其在大规模应用中可能会有所感知。
  5. 不适合对稳定性要求较高的场景:SPI 机制的动态性可能会增加系统的复杂性,对于对稳定性要求较高的场景,需要更严格的测试和控制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/863688.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Axure教程】账单列表和详情

账单列表和详情页在支付系统中不仅是用户了解财务状况和跟踪交易的关键工具&#xff0c;还有助于提高支付安全性、解决问题以及满足法律和财务要求。因此&#xff0c;设计一个清晰、易用且功能丰富的账单管理系统对于支付系统的成功运营和用户满意度至关重要。 今天作者就教大…

端点中心(Endpoint Central)的软件许可证管理

软件许可证管理 &#xff08;SLM&#xff09; 是从单个控制台管理整个组织中使用的软件许可证的过程。软件许可证是由软件发行商或分销商制作的法律文件&#xff0c;提供有关软件使用和分发的规则和指南&#xff0c;本文档通常包含条款和条件、限制和免责声明。 软件许可证管理…

原型和原型链理解

这个图大概能概括原型和原型链的关系 1.对象都是通过 _proto_ 访问原型 2.原型都是通过constructor 访问构造函数 3.原型是构造函数的 prototype 4.原型也是对象实例 也是通过 _proto_ 访问原型(Object.prototype) 5.Object.prototype的原型通过 _proto_ 访问 为null 那么…

全排列——力扣46

文章目录 题目描述解法:回溯题目描述 解法:回溯 //version 1 vector<vector<int>> permute(<

运动耳机什么样式的好、比较好的运动耳机推荐

在各类耳机中&#xff0c;运动耳机可以说是适用场景针对性较强的一类耳机。毕竟在运动场景中&#xff0c;对耳机的某些性能要求比较高&#xff0c;如防水能力、佩戴稳定性等等&#xff0c;一般的非运动耳机很难满足这些需求。寻找一款合适的蓝牙运动耳机并不困难。相比普通蓝牙…

python项目virtualenv环境部署正式项目和后台运行实践

pycharm创建virtualenv环境的项目&#xff1a; 在本地虚拟环境项目路径下生成依赖包记录文件&#xff0c;然后上传到linux 服务器项目路径下&#xff1a; 注意注意&#xff1a;要在虚拟环境中生成&#xff0c;才能将所有的项目依赖包构建在 requirements.txt文件中。 pip3 fre…

黑客(自学)

一、自学网络安全学习的误区和陷阱 1.不要试图先成为一名程序员&#xff08;以编程为基础的学习&#xff09;再开始学习 行为&#xff1a;从编程开始掌握&#xff0c;前端后端、通信协议、什么都学。 缺点&#xff1a;花费时间太长、实际向安全过渡后可用到的关键知识并不多。…

Java【算法 04】HTTP的认证方式之DIGEST认证详细流程说明及举例

HTTP的认证方式之DIGEST 1.是什么2.认值流程2.1 客户端发送请求2.2 服务器返回质询信息2.2.1 质询参数2.2.2 质询举例 2.3 客户端生成响应2.4 服务器验证响应2.5 服务器返回响应 3.算法3.1 SHA-2563.1.1 Response3.1.2 A13.1.3 A2 3.2 MD53.2.1 Request-Digest3.2.2 A13.2.3 A2…

SQL | 过滤数据

4-过滤数据 4.1-使用WHERE子句 数据根据 WHERE 子句中指定的搜索条件进行过滤。WHERE 子句在表名&#xff08; FROM 子句&#xff09;之后给出。 select prod_name,prod_price from products where prod_price 3.49; 上述语句查询价格为3.49的行&#xff0c;然后输出名字和…

多路复用select实现

select函数 int select(int nfds, fd_set *readfds,fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);nfds:是三个集合中编号最高的文件描述符&#xff0c;加上1readfds/writefds/exceptfds: 可读集合/可写集合/异常集合timeout NULL&#xff1a;永久阻塞0&…

JS 解决鼠标悬浮显示弹窗 迅速离开时弹窗显示到其他位置的延迟问题

解决该问题的思路就是&#xff0c;判断当前鼠标的位置是否在某个div上&#xff0c;如果在这个div上则取消显示悬浮弹窗消息。 首先监听鼠标的移动事件 鼠标移动时判断是否在div里面进行移动了 clientX表示鼠标X的位置 client Y表示鼠标Y的位置 拿到要判断的div元素 获取off…

【Uni-App】uview 开发多端应用,密码显示隐藏功能不生效问题

出现的问题&#xff1a; 使用uview组件u-input框密码绑定时会出现右侧密码显隐图标不显示的问题 思路&#xff1a; 1.看了下uview源码&#xff0c;发现这有一段注释&#xff0c;我们需要把源码修改一下&#xff0c;问题出在这里 这行代码修改为 :password"password || …

spring按条件注入@Condition及springboot对其的扩展

概述 spring的ioc极大的方便了日常开发&#xff0c;但随着业务的迭代。配置的一些参数在某些情况下需要按条件注入。 比如原先定义的db公共模块下&#xff0c;相关的配置和工具类只是基于mysql的。但是后续有模块需要使用mongo/es等其他数据库&#xff0c;又想继续使用db公共…

七. 定时器

定时器 1. EPIT定时器(1) 特征&#xff1a;(2) 结构&#xff1a;(3) 工作模式&#xff1a;(4) 寄存器(5) 配置步骤(6) 定时器消抖 2. GPT 定时器(1) 特征(2) 结构(3) 工作模式(4) 寄存器<1> GPTx_CR 配置<2> GPTx_PR 分频<3> GPTx_SR 状态<4> GPTx_CNT…

Vue+SpringBoot后台管理系统:Vue3+TypeScript项目搭建(一)

写在开始:一个搬砖程序员的随缘记录文章目录 一、Node安装二、Vue CLI安装三、相关的版本四、创建Vue3TypeScript项目五、Vue项目初始化六、项目启动 一、Node安装 查看Note版本 node -v查看npm版本 npm -v然后将npm升级至最新版本 npm -g install npm将npm下载源换至http:…

分布式异步任务处理组件(八)

分布式异步任务组件网络通信线程模型设计-- 大概说一下功能场景&#xff1a; 从节点和主节点建立连接&#xff0c;负责和主节点的网络IO通信&#xff0c;通信动作包括投票&#xff0c;心跳&#xff0c;举证等&#xff0c;步骤为读取主节点的信息&#xff0c;写入IO队列中&…

yum 安装本地包 rpm

有时直接yum install 有几个包死活下不下来 根据网址&#xff0c;手动下载&#xff0c;下载后上传至 centos 然后运行 sudo yum localinstall xxx.rpm 即可安装 参考 https://blog.csdn.net/weiguang1017/article/details/52293244

【Nginx】Nginx网站服务

国外主流还是使用apache&#xff1b;国内现在主流是nginx&#xff08;并发能力强&#xff0c;相对稳定&#xff09; nginx&#xff1a;高新能、轻量级的web服务软件 特点&#xff1a; 1.稳定性高&#xff08;没apache稳&#xff09;&#xff1b; 2.系统资源消耗比较低&#xf…

40G光模块在高速网络中的关键角色

40G光模块在高速网络中扮演着关键的角色。它是用于传输数据的光纤通信设备&#xff0c;具备高速数据传输能力&#xff0c;广泛应用于数据中心、电信运营商、企业网络等领域。本文我们来看看40G光模块在高速网络中是如何发挥它的作用的&#xff01; 一、认识40G光模块 为实现4…

vue手写多对多关联图,连线用leader-line

效果如图 鼠标滑动效果 关联性效果 <template ><div class="main" ref="predecessor"><div class="search"><div class="search-item"><div class="search-item-label">部门</div><…