当前位置: 首页 > news >正文

SPI机制详解

在上一篇 gRPC源码剖析-Server启动流程 有提到过SPI机制,SPI对于大多数业务开发人员可能并不熟悉,但是在各底层基础框架中用得还是比较多的,今天我们来详细了解一下。

一、SPI机制

SPI,全称是Service Provider Interface,就是为某个接口寻找服务实现的机制。

SPI机制遵循约定

1、服务提供方提供接口具体实现,并且必须在Jar包的META-INF/services目录下创建以“接口全名”为文件名,内容为实现类全类名。

2、主程序通过ServiceLoader动态加载实现类,需要扫描META-INF/services目录下配置文件找到实现类然后反射加载到JVM。

二、ServiceLoader

ServiceLoader和ClassLoader差不多也是用来加载类文件,但和ClassLoader有一些区别

1、ServiceLoader加载的是有共同接口的实现类,ClassLoader是个万能类加载器。

2、ServiceLoader加载类时依赖于META-INF/services的配置。

3、ServiceLoader实现了Interator接口,方便遍历出接口对应所有的实现类。

4、ServiceLoader类内部引用了ClassLoader进行类加载。

重要方法:ServiceLoader<S> load(Class<S> service),为给定的接口创建类加载器并通过反射加载具体的实现类。

三、一个打印例子

创建一个Maven多模块应用

1、api模块: 接口定义

2、yunda模块:韵达打印面单实现

配置文件

路径:/resources/META-INF/

service/org.api.PrintService

内容:org.yunda.YundaPrintServiceImpl

3、zto模块:中通打印实现

配置文件

路径:/resources/META-INF/

service/org.api.PrintService

内容:org.yunda.ZtoPrintServiceImpl

4、test模块:测试

必须引入 zto包依赖或yunda包依赖,否则虽然编译时不会报错,但运行时加载不到类的实现,这里折腾了很久。

四、JDBC使用SPI分析

1、驱动

mysql-connector-java.jar

META-INF/service/java.sql.Driver内容com.mysql.cj.jdbc.Driver

ojdbc.jar

META-INF/service/java.sql.Driver内容oracle.jdbc.OracleDriver

2、DriverManager

DriverManager是JDBC里管理不同数据库驱动的工具,核心与SPI有关的代码如下

根据注入的jdbc.drivers加载对应的数据库驱动。

注:SPI在底层框架使用的还是极其广泛的,除上上面讲到的JDBC数据库驱动,还有Spring、Dubbo、gRPC甚至淘宝交易平台早期也是用SPI来做业务隔离。

相关文章:

  • 学习JavaEE的日子 Day29 yield,join,线程的中断,守护线程,线程局部变量共享,线程生命周期
  • I.MX6ULL_Linux_系统篇(25) buildroot文件系统构建
  • C++自主点餐系统
  • WordPress Git主题 响应式CMS主题模板
  • python基本数据(如注释)
  • taro框架之taro-ui中AtSwipeAction的使用
  • Swift 周报 第四十八期
  • QT事件机制
  • 在Linux上使用nginx反向代理部署Docker网站
  • 【Java扫盲篇】String、String Buffer和String Builder的区别
  • iOS开发 - 转源码 - __weak问题解决
  • spikingjelly学习-使用单层全连接snn脉冲神经网络识别mnist数据集
  • websocket 内的操作码fin和opcode
  • 数据结构万字总结(超级详细)第二章——线性表
  • JVM虚拟机-实战篇
  • Angular 2 DI - IoC DI - 1
  • HTML中设置input等文本框为不可操作
  • Linux链接文件
  • mysql常用命令汇总
  • MySQL数据库运维之数据恢复
  • REST架构的思考
  • Selenium实战教程系列(二)---元素定位
  • Unix命令
  • 安装python包到指定虚拟环境
  • 彻底搞懂浏览器Event-loop
  • 面试总结JavaScript篇
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端设计模式
  • 设计模式(12)迭代器模式(讲解+应用)
  • 适配iPhoneX、iPhoneXs、iPhoneXs Max、iPhoneXr 屏幕尺寸及安全区域
  • 小程序01:wepy框架整合iview webapp UI
  • 一道面试题引发的“血案”
  • 追踪解析 FutureTask 源码
  • 字符串匹配基础上
  • linux 淘宝开源监控工具tsar
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • # include “ “ 和 # include < >两者的区别
  • #NOIP 2014# day.1 T2 联合权值
  • (Redis使用系列) Springboot 使用redis的List数据结构实现简单的排队功能场景 九
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (免费领源码)Python#MySQL图书馆管理系统071718-计算机毕业设计项目选题推荐
  • (四)鸿鹄云架构一服务注册中心
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (转)Scala的“=”符号简介
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .bat批处理(六):替换字符串中匹配的子串
  • .NET delegate 委托 、 Event 事件,接口回调
  • .NET Framework 的 bug?try-catch-when 中如果 when 语句抛出异常,程序将彻底崩溃
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .net下简单快捷的数值高低位切换
  • /proc/vmstat 详解
  • @RequestParam,@RequestBody和@PathVariable 区别
  • [ JavaScript ] JSON方法