学习ShardingSphere前置知识
学习ShardingSphere前置准备知识
一. SPI
SPI(Service Provider Interface)是一种Java的扩展机制,用于实现组件之间的松耦合。在SPI模型中,服务提供者(Service Provider)定义了一组接口,而服务的使用者可以根据接口编写代码。服务提供者则提供了接口的具体实现,这些实现可以被动态加载和替换。
下面是对SPI的理解:
1.接口定义: SPI的核心是一个接口,定义了一组规范或协议,以描述一种服务。以java.sql.Driver为例
2.服务提供者: 服务提供者是实现了接口的具体类。这些类通常通过在类路径中的META-INF/services目录下提供一个配置文件来注册自己。

其中在配置文件中的全类名为服务提供者,它实现了定义的接口

3.服务加载: 使用者通过查找和加载在类路径中的META-INF/services目录下的配置文件,获取服务提供者的实现类。Java的ServiceLoader类通常用于加载这些服务提供者。
使用ServiceLoader.load()进行服务发现与对应的配置文件的类进行加载
4.动态替换: 由于服务提供者的实现是通过配置文件注册的,因此可以在不修改使用者代码的情况下动态替换服务提供者。这使得系统更加灵活,并且可以在运行时适应不同的实现。
5.松耦合: SPI实现了松耦合的设计,允许开发者通过接口定义和服务提供者实现分离。这样,服务提供者可以独立于使用者进行开发、测试和部署。
二. ServiceLoader.load()
public final class ServiceLoader<S>implements Iterable<S>
{@CallerSensitivepublic static <S> ServiceLoader<S> load(Class<S> service) {ClassLoader cl = Thread.currentThread().getContextClassLoader();return new ServiceLoader<>(Reflection.getCallerClass(), service, cl);}// 实现Iterable接口必须要重写的方法 主要通过spi发现服务提供者,并进行驱动注册,加载public Iterator<S> iterator() {// create lookup iterator if neededif (lookupIterator1 == null) {lookupIterator1 = newLookupIterator();}return new Iterator<S>() {// record reload countfinal int expectedReloadCount = ServiceLoader.this.reloadCount;// index into the cached providers listint index;/*** Throws ConcurrentModificationException if the list of cached* providers has been cleared by reload.*/private void checkReloadCount() {if (ServiceLoader.this.reloadCount != expectedReloadCount)throw new ConcurrentModificationException();}@Overridepublic boolean hasNext() {checkReloadCount();if (index < instantiatedProviders.size())return true;return lookupIterator1.hasNext();}@Overridepublic S next() {checkReloadCount();S next;if (index < instantiatedProviders.size()) {next = instantiatedProviders.get(index);} else {next = lookupIterator1.next().get();instantiatedProviders.add(next);}index++;return next;}};}
}
它实现了Iterable接口,可以增强for循环,在遍历的时候进行相应的处理,接下来先熟悉下Iterable接口的使用
2. Iterable
public interface Iterable<T> {Iterator<T> iterator();default void forEach(Consumer<? super T> var1) {Objects.requireNonNull(var1);Iterator var2 = this.iterator();while(var2.hasNext()) {Object var3 = var2.next();var1.accept(var3);}}default Spliterator<T> spliterator() {return Spliterators.spliteratorUnknownSize(this.iterator(), 0);}
}
其中default方法为默认方法,使用default关键字为接口添加默认方法是为了在不破坏现有实现的情况下,为接口添加新的方法。
不需要强制实现
以下为是实现Iterable接口的例子,必须重写iterator()方法,类表明它可以被迭代(iterable),即可以被用于增强型 for 循环。
public class TestIterable<T> implements Iterable<T>{private List<T> list;public TestIterable(List<T> list){this.list = list;}@Overridepublic Iterator<T> iterator() {return list.iterator();}
}
下面分析下ServiceLoader.load入口出,在java.sql.DriverManager类内部调用,如下代码
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
Iterator<Driver> driversIterator = loadedDrivers.iterator();try {// 此处调用Iterator实现的hasNext方法,查找spi接口while (driversIterator.hasNext()) {driversIterator.next();}
} catch (Throwable t) {// Do nothing
}
return null;
}
以上代码通过对Iterator的实现,查找到对应路径下的文件,该路径即是spi的配置文件,文件里配置的是定义接口的实现类,
然后对该实现类进行类加载
/*** Loads and returns the next provider class.*/private Class<?> nextProviderClass() {if (configs == null) {try {//static final String PREFIX = "META-INF/services/";String fullName = PREFIX + service.getName();if (loader == null) {configs = ClassLoader.getSystemResources(fullName);} else if (loader == ClassLoaders.platformClassLoader()) {// The platform classloader doesn't have a class path,// but the boot loader might.if (BootLoader.hasClassPath()) {configs = BootLoader.findResources(fullName);} else {configs = Collections.emptyEnumeration();}} else {configs = loader.getResources(fullName);}} catch (IOException x) {fail(service, "Error locating configuration files", x);}}while ((pending == null) || !pending.hasNext()) {if (!configs.hasMoreElements()) {return null;}pending = parse(configs.nextElement());}String cn = pending.next();try {return Class.forName(cn, false, loader);} catch (ClassNotFoundException x) {fail(service, "Provider " + cn + " not found");return null;}}
ServiceLoader.load静态方法是 Java 提供的一种用于加载服务提供者实现的机制。
它是 Java SPI(Service Provider Interface)的一部分,用于在运行时动态加载服务接口的实现类。
具体来说,ServiceLoader.load 的作用是:
加载服务接口的实现类:通过 ServiceLoader.load(ServiceType.class),可以加载与指定服务接口 ServiceType 相关的所有实现类。这些实现类必须位于 META-INF/services/ 目录下的以服务接口全限定名为名称的配置文件中。
返回一个 ServiceLoader 对象:ServiceLoader.load 返回一个 ServiceLoader 对象,通过这个对象,你可以遍历加载到的所有服务提供者的实例。
public class TestSpi {public static void main(String[] args) {ServiceLoader<HumanTestSPI> loadHumanTestSPI = ServiceLoader.load(HumanTestSPI.class);//遍历加载到的所有服务提供者的实例。for (HumanTestSPI humanTestSPI:loadHumanTestSPI){humanTestSPI.speak();}}
}

以上为学习ShardingSphere前置知识,后面会用到大量的spi接口.
相关文章:
学习ShardingSphere前置知识
学习ShardingSphere前置准备知识 一. SPI SPI(Service Provider Interface)是一种Java的扩展机制,用于实现组件之间的松耦合。在SPI模型中,服务提供者(Service Provider)定义了一组接口,而服务…...
读书笔记-《数据结构与算法》-摘要3[选择排序]
选择排序 核心:不断地选择剩余元素中的最小者。 找到数组中最小元素并将其和数组第一个元素交换位置。在剩下的元素中找到最小元素并将其与数组第二个元素交换,直至整个数组排序。 性质: 比较次数(N-1)(N-2)(N-3)…21~N^2/2交换次数N运行…...
Arduino驱动MLX90614红外测温传感器(温湿度传感器)
目录 1、传感器特性 2、测量方法 3、硬件原理图 4、控制器和传感器连线图...
Ubuntu上传文件到SMB共享文件夹
0. 前言 公司有一些数据共享文件夹,平时可以把开发的重要文件放到上面备份。本人开发使用ubuntu系统,共享文件夹是windows的形式,想通过命令的方式,方便快捷,还可shell脚本自动化。 1. 安装挂载库 sudo apt-get upd…...
【Linux】基础IO--重定向理解Linux下一切皆文件缓冲区
文章目录 一、重定向1.什么是重定向2.dup2 系统调用3.理解输入重定向、输出重定向和追加重定向4.简易shell完整实现 二、理解linux下一切皆文件三、缓冲区1.为什么要有缓冲区2.缓冲区的刷新策略3.缓冲区的位置4.实现一个简易的C语言缓冲区5.内核缓冲区 一、重定向 1.什么是重定…...
RINEX介绍
一、RINEX是什么 Receiver Independent Exchange Format (RINEX) 是一种用于存储、交换和处理全球定位系统 (GPS) 接收机观测数据的标准化文件格式。RINEX 格式由国际电信联盟 (ITU) 和国际GPS服务 (IGS) 组织共同开发和维护。它提供了一种通用的数据格式,使得不同…...
ROS-ROS通信机制-服务通信
文章目录 一、服务通信基本知识二、自定义srv三、C实现四、Python实现 一、服务通信基本知识 服务通信也是ROS中一种极其常用的通信模式,服务通信是基于请求响应模式的,是一种应答机制。也即: 一个节点A向另一个节点B发送请求,B接收处理请求…...
chown和chmod
chown和chmod都是在Linux和Unix系统中用于设置文件和文件夹权限的命令,但它们的功能和用途有所不同。 功能:chown主要用于修改文件或文件夹的所有者和所属组,而chmod则主要用于修改文件或文件夹的读写执行权限。用途:如果想要授权…...
【GPU】linux 安装、卸载 nvidia 显卡驱动、cuda 的官方文档、推荐方式(runfile)
文章目录 1. 显卡驱动1.1. 各版本下载地址1.2. 各版本文档地址1.3. 安装、卸载方式 2. CUDA2.1. 各版本下载地址2.2. 各版本文档地址2.3. 安装、卸载方式2.4. 多版本 CUDA 切换方式 1. 显卡驱动 1.1. 各版本下载地址 https://www.nvidia.com/Download/Find.aspx?langzh-cn 1…...
6页手写笔记总结信号与系统常考知识大题知识点
题型一 判断系统特性题型二 求系统卷积题型三 求三大变换正反变换题型四 求全响应题型五 已知微分方程求系统传递函数题型六 已知系统的传递函数求微分方程题型七 画出系统的零极点图,并判断系统的因果性和稳定性 (笔记适合快速复习,可能会有…...
Qt-QSplitter正确设置比例
简短版本: splitter->setSizes({1000, 2000}); // 这个值至少跟像素值设置的一样大,或者更大,例如x10倍详细版本: setSizes 官方介绍如下: Sets the child widgets’ respective sizes to the values given in the…...
一篇吃透大厂面试题,2024找工作一帆风顺。
🏆作者简介,普修罗双战士,一直追求不断学习和成长,在技术的道路上持续探索和实践。 🏆多年互联网行业从业经验,历任核心研发工程师,项目技术负责人。 🎉欢迎 👍点赞✍评论…...
【1day】用友 U8 Cloud系统TaskTreeQuery接口SQL注入漏洞学习
注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现...
华为快应用中自定义Slider效果
文章目录 一、前言二、实现代码三、参考链接 一、前言 在华为快应用中官方提供了<slider>控件,但是这个控件的限制比较多,比如滑块无法自定义,所以这里进行下自定义,自己修改样式。 二、实现代码 整体效果如下: 源码如下…...
C语言每日一题(43)旋转链表
力扣 61 旋转链表 题目描述 给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。 示例 1: 输入:head [1,2,3,4,5], k 2 输出:[4,5,1,2,3]示例 2: 输入:head [0,1,2], …...
CCF计算机软件能力认证考试—202209-1如此编码
题目背景 某次测验后,顿顿老师在黑板上留下了一串数字 23333 便飘然而去。凝望着这个神秘数字,小 P 同学不禁陷入了沉思…… 题目描述 已知某次测验包含 � 道单项选择题,其中第 � 题(1≤�≤&…...
Ubuntu18.04安装Ipopt-3.12.8流程
本文主要介绍在Ubuntu18.04中安装Ipopt库的流程,及过程报错的解决方法,已经有很多关于Ipopt安装的博客,但经过我的测试,很多都失效了,经过探索,找到可流畅的安装Ipopt的方法,总结成本篇博客。 …...
linux 内核同步互斥技术之信号量
信号量 信号量允许多个进程同时进入临界区,大多数情况下只允许一个进程进入临界区,把信号量的计数值设置为 1,即二值信号量,这种信号量称为互斥信号量。可允许多个锁持有者。 和自旋锁相比,信号量适合保护比较长的临界…...
交通强国添力量 无人机巡航为何备受期待?
在高速建设交通强国的过程中,交通运输部海事局计划完善“陆海空天”一体化水上交通运输安全保障体系。无人机巡航系统将在提升海事船舶监管和水上搜救能力方面发挥关键作用,以构建更为全面的监管体系。尽管已初步建立了海事监管体系,但仍存在…...
【PID学习笔记 6 】控制系统的性能指标之二
写在前面 上文介绍了控制系统的稳态与动态、过渡过程、阶跃响应以及阶跃信号作用下过渡过程的四种形式。本文紧接上文,首先总结过渡过程的分类,然后介绍控制系统的性能评价,最后重点介绍控制系统性能指标中的单项指标。 一、过渡过程的分类…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
