SPI 机制

一、简述

本文介绍 SPI 机制。

二、什么是 SPI 机制

SPI(Service Provider Interface)机制是 Java 编程语言中的一种机制,用于实现组件之间的解耦和扩展。SPI 允许开发者编写服务接口(Service Interface),并在运行时动态地加载实现了该接口的服务提供者(Service Provider)。
SPI 机制的基本原理如下:

  1. 定义服务接口:开发者定义一个服务接口,描述了一组操作或功能,这些功能可以由不同的提供者来实现。
  2. 服务提供者编写服务:不同的服务提供者可以编写不同的服务(即实现该服务接口,并提供自己的实现逻辑)。
  3. 配置服务注册文件:每个服务提供者都需要在特定的位置提供一个描述文件,通常是META-INF/services/接口全限定名,文件内容为该接口实现类的全限定类名列表。
  4. 服务加载器加载服务:在程序运行时,Java 虚拟机会通过 SPI 机制加载并实例化这些服务提供者,然后调用其方法来完成具体的功能。

三、为什么使用 SPI 机制

  1. 假设我们有一个服务接口 Animal,定义了动物的基本行为:
public interface Animal {void makeSound();
}
  1. Animal 接口有一个实现类
public class Dog implements Animal {@Overridepublic void makeSound() {System.out.println("Dog barks: Woof woof!");}
}
  1. 编写接口和类的使用逻辑
public class Main {public void sound() {Animal animal = new Dog();animal.makeSound();}
}

上面的例子是传统的开发模式(在一个项目中定义接口,实现接口)。现在将以上内容拆分到两个项目:

  1. 在 A 项目中定义接口
public interface Animal {void makeSound();
}
  1. 在 A 项目中定义接口的使用逻辑(但是没有实现类)
import java.util.ServiceLoader;public class Main {public void sound() {// 使用 ServiceLoader 加载 Animal 接口的实现类ServiceLoader<Animal> animals = ServiceLoader.load(Animal.class);// 遍历并调用每个实现类的方法for (Animal animal : animals) {animal.makeSound();}}
}
  1. B 项目中引入 A 项目,并且实现 A 中的接口
public class Dog implements Animal {@Overridepublic void makeSound() {System.out.println("Dog barks: Woof woof!");}
}
  1. B 项目在 META-INF/services/Animal 文件中提供实现类的全限定类名:
com.example.Dog

上面两种方式可以实现同样的功能,第二种方式采用的是 SPI 机制。在 SPI 机制中,A 定义方法的执行逻辑,并开放了一个扩展点交由 B 实现,扩展点的具体功能是由实现者自己处理,这样就实现了解耦。可以看出 SPI 机制的优点在于它的松耦合性和扩展性,因为服务接口与具体的实现是分离的,开发者可以根据需要灵活地替换服务提供者接口的实现。

四、如何使用 SPI 机制

我们这里以 JDBC 为例来说明该如何使用 SPI。

4.1 定义服务接口

Java 团队在 java.sql 包中定义了 Driver 接口

package java.sql;import java.util.logging.Logger;public interface Driver {Connection connect(String url, java.util.Properties info)throws SQLException;boolean acceptsURL(String url) throws SQLException;DriverPropertyInfo[] getPropertyInfo(String url, java.util.Properties info)throws SQLException;int getMajorVersion();int getMinorVersion();boolean jdbcCompliant();public Logger getParentLogger() throws SQLFeatureNotSupportedException;
}

4.2 服务加载器加载服务

Java 团队在 java.sql.DriverManager类中使用 java.util.ServiceLoader来加载 java.sql.Driver接口的实现类(可能不止一个),并实现了一些逻辑。

package java.sql;import java.util.ServiceLoader;public class DriverManager {// 此处省略了一些逻辑内容private static void ensureDriversInitialized() {// 服务加载器加载服务ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);// 迭代遍历能够找到的服务实现Iterator<Driver> driversIterator = loadedDrivers.iterator();try {while (driversIterator.hasNext()) {driversIterator.next();}} catch (Throwable t) {// Do nothing}return null;}// 此处省略了一些逻辑内容
}

4.3 服务提供者编写服务

MySQL 团队在自己项目的 com.mysql.cj.jdbc 包中编写了针对 Java 团队 java.sql.Driver 接口的实现。

package com.mysql.cj.jdbc;import java.sql.DriverManager;
import java.sql.SQLException;public class Driver extends NonRegisteringDriver implements java.sql.Driver {public Driver() throws SQLException {}static {try {DriverManager.registerDriver(new Driver());} catch (SQLException var1) {throw new RuntimeException("Can't register driver!");}}
}

4.4 服务提供者配置服务注册文件

MySQL 团队在自己项目中 META-INF/services/ 目录下配置了服务注册文件。该文件名是接口的全限定名称,文件里面的内容是实现类的全限定名称。
image.png

4.5 SPI 机制处理流程

  1. Java 团队预先定义好接口,定义好接口的使用逻辑
  2. MySQL 团队实现接口,并以规定好的方式配置服务注册文件(即配置文件必须在 META-INF/services 目录下,文件名称以接口全限定名称命名,文件内容为接口实现类的全限定名称)
  3. 当在项目中引入了 MySQL 的驱动之后,JDBC 就能根据之前的服务注册文件找到对应的实现类
  4. 接下来,可以使用 JDBC 连接、操作数据库了

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

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

相关文章

计算机网络 路由器基本配置

一、实验内容 1、按照下表配置好PC机IP地址和路由器端口IP地址 2、配置好路由器特权密文密码“abcd&#xff0b;两位班内序号”和远程登录密码“star” 3、验证测试 a.验证各个接口的IP地址是否正确配置和开启 b.PC1 和 PC2 互ping c.验证PC1通过远程登陆到路由器上&#…

目前深圳嵌入式单片机就业环境如何?

深圳作为中国的科技创新中心之一&#xff0c;嵌入式行业的就业环境相对较好。我这里有一套嵌入式入门教程&#xff0c;不仅包含了详细的视频讲解&#xff0c;项目实战。如果你渴望学习嵌入式&#xff0c;不妨点个关注&#xff0c;给个评论222&#xff0c;私信22&#xff0c;我在…

docker 上达梦导入dump文件报错:本地编码:PG GBK,导入女件编码:PGGB18030

解决方案&#xff1a; 第一步进入达梦数据容器内部 docker exec -it fc316f88caff /bin/bash 第二步&#xff1a;在容器中 /opt/dmdbms/bin目录下 执行命令 cd /opt/dmdbms/bin./dimp USERIDSYSDBA/SYSDBA001 FILE/opt/dmdbms/ZFJG_LJ20240407.dmp SCHEMASZFJG_LJUSERIDSYSD…

linux安装

1、解压vm ware压缩包 2双击安装 3点击自定义硬件 4双击cd/dvd,给虚拟光驱里放虚拟光盘 5记得启动时链接勾上&#xff0c;勾上起点系统时 虚拟光驱才会一起启动 6点击确认即可&#xff01; 开机 选择第一个 7进入图形化安装界面 8设置时区 9选择硬盘 10网络配置 开启以太网&am…

C语言进阶课程学习记录-数组指针和指针数组分析

C语言进阶课程学习记录-数组指针和指针数组分析 实验-数组指针的大小实验-指针数组小结 本文学习自狄泰软件学院 唐佐林老师的 C语言进阶课程&#xff0c;图片全部来源于课程PPT&#xff0c;仅用于个人学习记录 实验-数组指针的大小 #include <stdio.h>typedef int(AINT…

【MoS2】应变增强的单层MoS2光电探测器

这篇文章的标题是《Strain-Enhanced Large-Area Monolayer MoS2 Photodetectors》&#xff0c;作者是Borna Radatovic等人&#xff0c;发表在《ACS Applied Materials & Interfaces》期刊的2024年第16卷。文章主要研究了应变增强的大面积单层MoS2光电探测器的性能和应用潜力…

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题1

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题1 信息安全管理与评估 网络系统管理 网络搭建与应用 云计算 软件测试 移动应用开发 任务书&#xff0c;赛题&#xff0c;解析等资料&#xff0c;知识点培训服务 添加博主wx&#xff1a;liuliu548…

Testng测试框架(3)-数据驱动TestNG@DataProvider

TestNG 是一个强大的 Java 测试框架&#xff0c;它提供了许多高级功能&#xff0c;如参数化测试、依赖注入、分组等。其中&#xff0c;DataProvider 是 TestNG 中一个非常有用的注解&#xff0c;用于为测试方法提供数据。 DataProvider 的作用 使用 DataProvider 注解的方法可…

java数据结构与算法刷题-----LeetCode260. 只出现一次的数字 III

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 与运算取末尾1分组 与运算取末尾1分组 解题思路&#xff1a;时间…

文献速递:深度学习肝脏肿瘤诊断---基于多相增强 CT 和临床数据的恶性肝肿瘤鉴别诊断深度学习

Title 题目 Deep learning for diferential diagnosisof malignant hepatic tumors based on multi-phase contrast-enhanced CT and clinical data 基于多相增强 CT 和临床数据的恶性肝肿瘤鉴别诊断深度学习 Abstract 摘要 Liver cancer remains the leading cause of can…

计算机网络——TCP和UDP协议

目录 前言 前篇 引言 TCP与UDP之间的区别 TCP 三次握手 为什么要三次握手而不是两次握手&#xff1f; 丢包问题与乱序问题的解决 四次挥手 为什么客户端需要等待超时时间&#xff1f; UDP协议 TCP和UDP的主要区别 前言 本博客是博主用于复习计算机网络的博客&…

软件开发安全备受重视,浙江某运营商引入CWASP认证课程,

​浙江省某大型运营商是一家实力雄厚、服务优质的通信运营商&#xff0c;致力于为全省用户提供优质、高效的通信服务。数字时代&#xff0c;该运营商顺应信息能量融合发展趋势&#xff0c;系统打造以5G、算力网络、能力中台为重点的新型信息基础设施&#xff0c;夯实产业转型升…

Redis入门到通关之五大基本数据类型及其使用场景

文章目录 一 什么是NoSQL&#xff1f;二 Redis是什么&#xff1f;三 Redis五大基本类型1 String&#xff08;字符串&#xff09;应用场景 2 List&#xff08;列表&#xff09;应用场景 3 Set&#xff08;集合&#xff09;4 sorted set&#xff08;有序集合&#xff09;应用场景…

代码随想录阅读笔记-回溯【组合总和II】

题目 给定一个数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 说明&#xff1a; 所有数字&#xff08;包括目标数&#xff09;都是正整数。解集不能包含重复的组…

VBA中如何对工作表进行排序

代码 在VBA中对工作表进行排序的最简单方法是直接使用Move方法来移动工作表。 Sub SortSheetsByNameDescending()Dim sheetsDim sheet As WorksheetDim i As Integer, j As IntegerDim sortedSheets() As Array 获取当前工作簿中的所有工作表Set sheets ThisWorkbook.Sheets…

MySQL索引、B+树相关知识汇总

MySQL索引、B树相关知识汇总 一、有一个查询需求&#xff0c;MySQL中有两个表&#xff0c;一个表1000W数据&#xff0c;另一个表只有几千数据&#xff0c;要做一个关联查询&#xff0c;如何优化&#xff1f;1、为关联字段建立索引二、小表驱动大表 二、b树和b树的区别1、更高的…

什么是NLP?

&#x1f916;NLP是什么&#xff1f;&#x1f916; NLP&#xff08;Natural Language Processing&#xff09;&#xff0c;全称自然语言处理&#xff0c;是人工智能不可或缺的一环&#xff0c;它搭建了人与计算机之间沟通的桥梁&#x1f309;。 &#x1f6e0;️NLP强大功能一…

高校实习管理系统的设计与实现(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统高校实习管理系统信息管理难度大&#xff0c;容错率低&am…

给Parallels Desktop虚拟机下的Linux磁盘扩容

本文是以Ubuntu为例演示&#xff0c;涉及到的命令在centos里也同样适用 一、扩容前查看磁盘容量 二、开始扩容操作 第一步&#xff1a;打开PD分配更大的磁盘空间&#xff0c;要保证有足够大的扩容空间 我的pd里给ubuntu分配了64G的磁盘空间&#xff0c;所以我大概还能扩容34G…

linux学习:标准IO

目录 接口 打开文件 关闭文件 读写 每次一个字符的读写标准 IO 函数接口 每次一行的读写标准 IO 函数接口 每次读写若干数据块的标准 IO 函数接口 获取或设置文件当前位置偏移量 标准格式化 IO 函数 系统 IO 的最大特点一个是更具通用性&#xff0c;不管是普通文件、管…