• SPI机制是什么?


    一、SPI机制是什么?

    spi全称为 (Service Provider Interface),是JDK内置的一种服务提供发现机制。SPI是一种动态替换发现的机制,一种解耦非常优秀的思想。

    spi的工作原理: 就是ClassPath路径下的META-INF/services文件夹中, 以接口的全限定名来命名文件名,文件里面写该接口的实现。然后再资源加载的方式,读取文件的内容(接口实现的全限定名), 然后再去加载类。

    spi可以很灵活的让接口和实现分离, 让api提供者只提供接口, 第三方来实现。

    优点:

    • 使用Java SPI机制的优势是实现解耦,使得第三方服务模块的装配控制的逻辑与调用者的业务代码分离,而不是耦合在一起。应用程序可以根据实际业务情况启用框架扩展或替换框架组件。

    缺点:

    • 虽然ServiceLoader也算是使用的延迟加载,但是基本只能通过遍历全部获取,也就是接口的实现类全部加载并实例化一遍。如果你并不想用某些实现类,它也被加载并实例化了,这就造成了浪费。获取某个实现类的方式不够灵活,只能通过Iterator形式获取,不能根据某个参数来获取对应的实现类。
    • 多个并发多线程使用ServiceLoader类的实例是不安全的。

    二、SPI如何使用

    那么现在有这样的场景:当我的项目里面有什么支付模块我就使用什么样的支付模块,比如说有支付宝支付模块就选择支付宝、有微信支付模块我就选择微信支付、同时有多个的时候,我默认选择第一个,此时我们就可以使用SPI,先看下如何使用。

    1、创建META-INF/services文件夹,然后创建一个以Pay接口全限定名为名字的文件

    2、在文件中编写想要实现哪个Pay的实现类(AliPay,WechatPay,BankCardPay),注意也要是全限定名。假如是是支付宝支付的模块,上面文件的内容:com.taolong.dubbo.spi.strategy.AliPay

    3、获取Pay并调用

    获取并调用的逻辑,我就修改下上面的策略模式中的Context的invokerStrategy方法,这里假设默认使用第一个

    public void invokeStrategy(){
        ServiceLoader payServiceLoader = ServiceLoader.load(Pay.class);
        Iterator iterator = payServiceLoader.iterator();
        if (iterator.hasNext()){
            iterator.next().pay();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    三、SPI的优秀实现案例

    我们来看一个真实的使用上述SPI的例子—数据库驱动(Driver)。

    我们知道,当我们的项目里面使用引用了mysql的驱动pom依赖时,我们的项目里面会自动选择使用mysql的驱动,我们甚至不需要手动去加载。我们来看看它的具体实现。

    1、首先看一下java.sql.Driver的类,这里面也是相当于定义了一个规范

    2、其次看mysql驱动包的META-INF/services文件夹下面有没有指定的文件

    很熟悉,命名就是java.sql.Driver

    3、打开文件查看一下文件内容

    这里面就能看到我们的mysql的驱动了,到这里基本上就确认这也是使用SPI实现的,顺便说一下,现在为什么我们不需要使用Class.forName()去加载驱动了,这是因为DriverManager使用SPI的机制已经帮我们加载好了,我们来看看DriverManager的类

    不管是文件名还是文件内容都是全限定名,所以通过反射很容易创建相应的类

    在现有框架中的使用

    其实了解SPI机制是因为最近看SpringBoot代码的时候发现的,我们知道在SprngBoot中好多的配置和实现都有默认的实现,我们只需要修改部分配置,比如数据库配置,我们只要在配置文件中写上对应的url,username,password就可以使用了。其实他这边用的就是SPI的方式实现的

    不过Spring使用的只是和JDK中的原理相同而已。

    JDK使用的工具类是ServiceLoader

    Spring中使用的类是SpringFactoriesLoader,在 org.springframework.core.io.support包中

    区别:

    文件路径不同 spring配置放在 META-INF/spring.factories中

  • 相关阅读:
    ABAQUS 求解应力强度因子
    【我的Android进阶之旅】在Android中使用MediaPipe库在实时视频源上实现人脸网格Face Mesh的绘制
    作为产品经理,你是如何分析和管理你的产品需求的?
    小程序AI智能名片S2B2C商城系统:四大主流商业模式深度解析与实战案例分享
    Springcloud中间件-----分布式搜索引擎 Elasticsearch
    顺序表(c++类模板实现)
    【Linux初阶】信号入门 | 信号基本概念+信号产生+核心转储
    Illegal key size or default parameters
    【第66篇】深度学习在视频多目标跟踪中的应用综述
    【牛客网刷题】(第四弹)多道中等难度题,早日拿offer,快来看看
  • 原文地址:https://blog.csdn.net/m0_67390379/article/details/126040615