服务发现机制SPI居然是破坏者?!

简介: 前言主要介绍下 Java 中的 SPI 机制 。Springboot 的 SPI 机制 咱们在下文 Springboot的自动装配中再说~ 😝 嘿嘿至于 [[ dubbo 的 SPI 机制]],还没时间深入了解,简单知道了它的 SPI 的自适应扩展机制,以及下面这些扩展~(超级多扩展的~)🐷冲冲冲!什么是SPI呢?SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在 ClassPath 路径下的 META-INF/services 文件夹查找文件,自动加载文件里所定义的类(定义多少,加载多少)它是 Java 提供的一套用

前言


主要介绍下 Java 中的 SPI 机制 。


SpringbootSPI 机制 咱们在下文 Springboot自动装配中再说~ 😝 嘿嘿

至于 [[ dubboSPI 机制]],还没时间深入了解,简单知道了它的 SPI 的自适应扩展机制,以及下面这些扩展~(超级多扩展的~)🐷


网络异常,图片无法展示
|



网络异常,图片无法展示
|


冲冲冲


什么是SPI呢?


SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在 ClassPath 路径下的 META-INF/services 文件夹查找文件,自动加载文件里所定义的类(定义多少,加载多少)

它是 Java 提供的一套用来被第三方实现或者扩展的接口


JAVA SPI 实践


步骤


  1. 先定义一个接口和它的实现类


  1. 再在 resources 下添加  META-INF/services两个文件夹  在该文件夹中新建一个普通文本,名字为 接口的全名 ,并将 接口的实现类全名 添加到文本中,多个的话进行换行操作


  1. 最后在代码中调用 ServiceLoader.load 方法即可实现


项目结构图


网络异常,图片无法展示
|


spi文件内容


网络异常,图片无法展示
|


源码如下


接口


public interface IJava4ye {
    void say();
}
public class Java4yeImpl implements IJava4ye{
    @Override
    public void say() {
        System.out.println(" 【java4ye】 杰伦 杰伦!");
    }
}
复制代码


测试类


public class SpiTest {
    @Test
    public void spiTest(){
        ServiceLoader<IJava4ye> load = ServiceLoader.load(IJava4ye.class);
        for (IJava4ye iJava4ye : load) {
            iJava4ye.say();
        }
    }
}
复制代码


结果


网络异常,图片无法展示
|


是不是非常的方便,还有 IOC 的感觉 哈哈😄


JDBC实例


那么实践完,我们再来看看 JDBC  这个小案例😝


网络异常,图片无法展示
|


可以看到我们使用的 MySQLJDBC 包中就有这么一个例子~🐷


而这个 java.sql.Driver 文件中就定义了这么一个实现类~👇


com.mysql.cj.jdbc.Driver
复制代码


Driver源码


网络异常,图片无法展示
|


可以发现这里有一个静态代码块,随着类被加载,它会直接往 DriverManager 中注册这个 Driver 驱动器 。


那有什么作用呢?


简单看下这个 JDBC 的写法 ,可以发现,之前我们都是要手动去写这个

Class.forName 来加载这个驱动器,但是用了这个 SPI 后,那不就可以省略这行代码了吗~😄 哈哈🐷


以后我们都不用管厂商定义了啥,直接使用 DriverManager.getConnection(url, username, password); 就可以获取到这个连接了,代码中就不会出现这种硬编码~ 灵活多了🐷 (当然不开发框架或者自己多折腾好像也用不上呀😝 哈哈哈)


网络异常,图片无法展示
|


JAVA SPI 原理探索


疑惑


不知道小伙伴们实践完会不会有点小疑惑,这个 SPI 一定要用 ServiceLoader.load 方法去加载的吗?


4ye 也不知道是不是  哈哈,但是 DriverManager 中就是这么使用的😝


详细请看下图👇


网络异常,图片无法展示
|


网络异常,图片无法展示
|


破坏双亲委派机制


我们都知道在 Java 中有这个双亲委派机制 ,像上面 DriverManager  这种做法,其实是破坏了这个 双亲委派机制


因为这个实现类是属于第三方类库 mysql

而这个 Driver 接口是在jdk 自身的 lib  --》 rt.jar 中的

它是由 根类加载器BootstrapClassloader 加载的, 而它的实现类却是在第三方的包中,这样子 BootstrapClassloader 是无法加载的。


那么怎样才能加载第三方包中的类呢?


看看 ServiceLoader 这个类我们就清楚啦~ 😝


网络异常,图片无法展示
|


ServiceLoader源码


网络异常,图片无法展示
|


可以发现这里有很显眼的一句话


ClassLoader cl = Thread.currentThread().getContextClassLoader();
复制代码


通过 当前线程的上下文类加载器 去加载的!


那么这个 当前线程的上下文类加载器 中又是用了哪个 classLoader 呢?


在源码中一番搜索之后,我们可以看到在启动器Launcher 中有这么一段代码,将 AppClassLoader 赋值给 ClassLoader 变量,并将其设置到当前线程中。😋


网络异常,图片无法展示
|


那么结论也很明显啦,SPI 是通过应用程序类加载器AppClassLoader 去加载第三方包中的类的。


总结


java 提供了这个服务发现机制SPI ,可以方便我们对某个接口进行扩展,实现模块的热插拔,而缺点就是,灵活度不高,配置文件中由多少实现类,都会被加载到内存中,不管有没有使用到~🐷


原理图奉上~


网络异常,图片无法展示
|



目录
相关文章
|
6月前
|
机器学习/深度学习 并行计算 测试技术
5倍加速!PAI-EAS在线服务优化:ResNet50模型推理性能调优指南
本文系统分析ResNet50推理性能瓶颈,结合TensorRT加速、模型剪枝、批量推理及CUDA多流并行等技术,实现吞吐量提升56.7倍、延迟降低至22ms,同时优化GPU利用率与服务稳定性,提供完整的生产部署验证方案。
322 5
|
运维 测试技术
通义灵码测评
作为一名运维人员,通过使用通义灵码进行业务、功能及环境测试,显著提高了工作效率。以前需自行查找或编写代码,不仅速度慢且易出错。通义灵码能够快速响应需求,即时生成所需代码,大幅减少错误和修改时间,优化了工作流程。
177 1
|
人工智能 自然语言处理
冬天到了,用OmniGen生成一个温暖的拥抱
近期,北京智源人工智能研究院(BAAI)正式推出了一款名为OmniGen的新型多功能图像生成模型。
|
缓存 算法 数据处理
如何选择合适的内存访问模式
【10月更文挑战第20天】如何选择合适的内存访问模式
379 1
|
机器人
太空采矿:地球资源枯竭后的替代方案
【10月更文挑战第10天】太空采矿作为地球资源枯竭后的替代方案,具有广阔的前景和潜力。然而,要实现太空采矿的商业化和可持续发展,还需要克服一系列技术、经济和法律挑战。未来,随着技术的不断进步和国际合作的加强,太空采矿将成为人类社会新的资源来源和经济增长点。让我们共同期待太空采矿的美好未来!
|
JavaScript 前端开发 Java
一文让你了解微服务契约测试
谈到微服务,大家都想到契约测试,到底什么是契约测试呢,为什么要使用契约测试呢,关于这样的文章很多,本文将结合Spring Boot让你了解微服务契约测试。
233 0
一文让你了解微服务契约测试
|
监控 持续交付 开发工具
Flow
Flow
542 6
|
人工智能 安全 自动驾驶
人工智能浪潮下的隐私保护:挑战与策略
本文旨在探讨人工智能技术发展对个人隐私保护所带来的挑战,并提出相应的应对策略。通过分析当前人工智能应用中数据收集和处理的常见模式,揭示其对个人隐私的潜在威胁。同时,结合最新的法律法规和技术手段,提出一系列隐私保护措施,旨在平衡技术创新与个人权益的保护。
633 0
|
网络协议 搜索推荐 数据库
子域名和主域名的区别
域名是网站或 URL 的名称,也称为主机名,域名指向指定的IP地址。如果您是第一次创建网站,甚至已有网站,您可能会遇到许多新术语,例如“主域”和“子域”。子域名和主域名算是域名的两种常见形式。
1335 15
|
编解码 Linux
ZC-OFDM模糊函数原理及仿真
ZC-OFDM模糊函数原理及仿真
383 0