JDK SPI 和 Dubbo SPI

news2025/1/8 5:22:58

SPI (Service Provider Interface),简单翻译就是服务提供接口,这里的“服务”泛指任何一个可以提供服务的功能、模块、应用或系统,会预留一些口子或者扩展点,只要按照既定的规范去开发,就可以动态加载一些不同的实现类,以实现一些自定义的扩展。

JDK自带SPI实现机制,但是也有很多对JDK的SPI做增强的实现,如Dubbo中的SPI,下边就对比JDK的SPI和Dubbo的SPI。

JDK SPI

JDK是通过ServiceLoader实现了SPI,具体来看ServiceLoader的核心代码逻辑

image

核心流程分为三块:

  • 第一块,将接口传入到ServiceLoader.load方法后,得到了一个内部类的迭代器。
  • 第二块,通过调用迭代器的hasNext方法,读取/META-INF/services/接口类路径这个资源文件内容,并逐行解析出所有实现类的类路径。
  • 第三块,将所有实现类的类路径通过Class.forName反射方式进行实例化对象。

这个地方,每调用一次ServiceLoader的load方法,就会创建新的实例对象,当调用load方法的次数很少时,创建新的实例化对象影响并不大,也就占用了一点内存,可以忽略不记。当调用load方法的频率比较高,那么每次调用都要读取文件、解析文件、反射实例化这几步,就会影响磁盘IO读取、内存开销也会明显增加。

每次调用load方法的时候,想要拿到其中一个实现类,因为不知道想要的实现类在迭代器中的位置,需要遍历所有的实现类,项目中,很多需要获得指定的实现类,会产生很多雷同的代码。

JSK SPI的问题

JDK的SPI创建出多个实例化对象,有两个问题:

  • 问题1,使用load方法频率高,容易影响IO吞吐和内存消耗。
  • 问题2,使用load方法想要获取指定实现类,需要自己进行遍历并编写比较代码。

针对问题1,我们可以尝试增加缓存,在第一次调用load方法时,通过读取文件、解析文件、反射实例化拿到接口的所有实现类并缓存,后续的调用直接从缓存中读取,减少资源消耗,提升性能。

针对问题2,问题就是解决遍历查找的时间复杂度是O(n),将时间复杂度从O(n)降低到O(1),采用空间换时间的方式,可以使用Map,Map 支持通过不同的一个对象获取另外一个对象,类似通过别名获取另外一个对象,比较符合常规查找操作。

Dubbo SPI

为了弥补我们分析的 JDK SPI 的不足,Dubbo 也定义出了自己的一套 SPI 机制逻辑,既要通过 O(1) 的时间复杂度来获取指定的实例对象,还要控制缓存创建出来的对象,做到按需加载获取指定实现类,并不会像 JDK SPI 那样一次性实例化所有实现类。

JDK SPI 的使用三部曲:

  • 首先,定义一个接口。
  • 然后,定义一些类来实现该接口,并将多个实现类的类路径添加到“/META-INF/services/ 接口类路径”文件中。
  • 最后,使用 ServiceLoader 的 load 方法加载接口的所有实现类。

学习来源:极客时间 《Dubbo源码剖析与实战》 学习笔记 Day12

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

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

相关文章

MES和金蝶云星空接口打通对接实战

四化智造MES(WEB)和金蝶云星空接口打通对接实战数据源平台:四化智造MES(WEB)MES建立统一平台上通过物料防错防错、流程防错、生产统计、异常处理、信息采集和全流程追溯等精益生产和精细化管理,帮助企业合理安排生产排…

机器视觉_HALCON_HDevelop用户指南_2.Getting Started

文章目录前言二、Getting Started2.1. 运行HDevelop2.2. 运行示例程序前言 标题本来想用“开始使用”或“快速上手”,不过感觉怪怪的,干脆就叫Getting Started吧,因为许多开发手册,开始上手的那节就叫这个名字。 本文是接上一篇…

【人工智能原理自学】LSTM网络:自然语言处理实践

😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本文讲解LSTM网络:自然语言处理实践,一起卷起来叭! 目录一、“RNN”二、编程实验一、“RNN” 上节课我们利用词嵌入把句子转化为词向量序列…

手把手本地搭建服务器笔记1

需要的下载的东西: vmware (百度网盘)银河麒麟镜像xshell,xftp安装vmware: 下载的包里有密钥,安装的时候就直接把密钥扔里面就好了 镜像处理: vmware左上角文件-新建虚拟机-典型,下一步 -安装程序光盘映像文件&am…

基于嵌入式物联网技术的智慧病房方案设计

文章目录前言1、要求2、系统设计3、功能模块3、系统功能模块图一、stm32控制模块原理图二、各功能模块的实现1、整个系统的基本配置2、RTOS多任务1、设计线程2、配置主函数代码3、温湿度读取模块(I2C)4、LED定时开关灯(pwm)5、按键实现报警信号6、脉搏&血氧数据读取7、UART…

【HTML】基础的入门学习

HTML 菜鸟教程 简介 一般结构&#xff1a; <!DOCTYPE html> 声明为 HTML5 文档<html> 元素是 HTML 页面的根元素<head> 元素包含了文档的元&#xff08;meta&#xff09;数据&#xff0c;如 <meta charset"utf-8"> 定义网页编码格式为 ut…

proteus仿真软件中芯片的命名规则与封装方法(详细版)

第一&#xff1a;PCB封装库命名规则 1、集成电路&#xff08;直插&#xff09; 用DIP-引脚数量尾缀来表示双列直插封装​ 尾缀有N和W两种,用来表示器件的体宽​ 为体窄的封装&#xff0c;体宽300mil,引脚间距2.54mm​ 为体宽的封装, 体宽600mil,引脚间距2.54mm​ 如&#…

11、关联数据库

文章目录11、关联数据库11.1 常规方式11.2 常规操作【尚硅谷】idea实战教程-讲师&#xff1a;宋红康 生活是属于每个人自己的感受&#xff0c;不属于任何别人的看法 11、关联数据库 11.1 常规方式 找到数据库选项&#xff1a; 添加指定数据库&#xff1a; 配置MySQL数据库…

5. 网络编程之UDP编程

1. UDP协议的特点 相比与TCP协议来说&#xff0c;UDP协议就显得相对比较简单了。 (1) UDP是无连接的   即发送数据之前不需要建立连接(当然&#xff0c;发送数据结束时也没有连接可释放)&#xff0c;因此减少了开销和发送数据之前的时延。 (2) UDP使用尽最大努力交付   即…

78、Points2NeRF: Generating Neural Radiance Fields from 3D point cloud

简介 github&#xff1a;https://github.com/gmum/points2nerf 由于点云的大小和复杂性&#xff0c;处理这些点云具有挑战性&#xff0c;现有的方法通过将网格拟合到点云并渲染来解决这个问题&#xff0c;这种方法导致结果可视化的保真度降低&#xff0c;并遗漏了在计算机图形…

HashTable HashMap ConcurrentHashMap 的介绍以及区别

目录 &#x1f407;今日良言:投资自己才是最好的投资 &#x1f409;一.HashMap. &#x1f415;二.HashTable &#x1f40d;三.ConcurrentHashMap &#x1f402;四.三者的区别 &#x1f407;今日良言:投资自己才是最好的投资 时隔四十多天,今天博主要更新了. 后续内容也是精…

[机器学习]损失函数DLC

一、损失函数的概念 损失函数(Loss Function)是用于评估预测结果和真实结果之间差距的一个公式&#xff0c;为模型优化指明方向。在模型优化过程中一般表述为&#xff1a;或 与针对整个训练集的代价函数(Cost Function)不同&#xff0c;损失函数通常仅针对单个训练样本。可以归…

RK3568平台开发系列讲解(驱动基础篇)Linux 内核源码介绍

🚀返回专栏总目录 文章目录 一、目录树概览二、快速确定主板关联代码2.1、基础代码2.2、驱动代码沉淀、分享、成长,让自己和他人都能有所收获!😄 📢进行嵌入式 Linux 产品开发,往往需要对内核进行裁剪和定制,以满足嵌入式产品的功能和性能需求。 一、目录树概览 解压…

Python---学生管理系统(pyinstaller)

专栏&#xff1a;python 个人主页&#xff1a;HaiFan. 专栏简介&#xff1a;本专栏主要更新一些python的基础知识&#xff0c;也会实现一些小游戏和通讯录&#xff0c;学时管理系统之类的&#xff0c;有兴趣的朋友可以关注一下。 学生管理系统前言创建入口函数新增学生insert展…

行为型模式-迭代器模式

1.概述 定义&#xff1a;提供一个对象来顺序访问聚合对象中的一系列数据&#xff0c;而不暴露聚合对象的内部表示。 2.结构 迭代器模式主要包含以下角色&#xff1a; 抽象聚合&#xff08;Aggregate&#xff09;角色&#xff1a;定义存储、添加、删除聚合元素以及创建迭代器…

实战案例:Python批量识别银行卡号码并且写入Excel,初学者也可以轻松使用~

大家好&#xff0c;这里是程序员晚枫&#xff0c; 今天我们继续学习Python自动化办公&#xff1a;每次有新员工入职&#xff0c;都要收集大量的工资卡信息&#xff0c;并且生成Excel文档&#xff0c;能不能用Python准确、快速地解决呢&#xff1f; 今天我们就来学习一下&…

【CCNA | 网络模拟器CPT系列】Cisco Packet Tracer 8.2.0 的安装 Ⅰ

目录1. 下载 Cisco Packet Tracer2. 安装 Cisco Packet Tracer&#xff08;1&#xff09;许可协议界面&#xff08;2&#xff09;选择安装目录&#xff08;3&#xff09;选择开始菜单文件夹&#xff08;4&#xff09;选择附加任务&#xff08;5&#xff09;确认设置选择&#x…

K8S环境安装

K8S环境安装 下面是环境的主机名和IP 主机名ipk8smaster192.168.68.150k8snode1192.168.68.151k8snode2192.168.68.152 1、安装docker 配置yum源 sudo yum install -y yum-utils sudo yum-config-manager \ --add-repo \ http://mirrors.aliyun.com/docker-ce/linux/centos/d…

不受支持的 Mac 上的通用控制(现已支持 macOS Ventura)

现已支持 macOS Ventura 请访问原文链接&#xff1a;不受支持的 Mac 上的通用控制&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 本文为 在不受支持的 Mac 上安装 macOS Ventura、Monterey、Big Sur (OpenCore Legacy Pa…

【Effective_Objective-C_5内存管理】

文章目录前言29.理解引用计数引用计数的工作原理关闭ARC模式引用计数的增减理解一下引用计数存在属性存取方法中的内存管理自动释放池保留环要点30.以ARC简化引用计数使用ARC时必须遵循的方法和命名规则-变量的内存管理语法意义ARC如何清理实例变量覆写内存管理的方法要点31.在…