• java:SPI使用


    java:SPI使用

    1 前言

    SPI,即Service Provider Interface。面向的对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。

    Java SPI 就是提供这样的一个机制:为某接口(interface)寻找服务实现(impl)的机制。Java SPI 的具体约定为:当服务接口的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里(可置于resources目录下)创建一个以服务接口命名的文件,该文件内容写入实现该服务接口的具体实现类(全限定类名,多个实现类换行写入即可)而当外部程序装配此模块时,就能通过该jar包下META-INF/services/里的接口服务配置文件找到具体实现类,并装载实例化,完成模块的注入。基于这样的约定就能很好的找到服务接口的实现类,而不需要在代码里制定。

    jdk提供服务实现查找的一个工具类,即:java.util.ServiceLoader。

    2 使用

    2.1 创建服务接口及其实现类

    创建服务接口:

    package com.xiaoxu.spi;
    
    public interface XiaoxuSpiTest {
        void spiRun();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    创建该服务接口的两个实现类:

    package com.xiaoxu.spiImpl;
    
    import com.xiaoxu.spi.XiaoxuSpiTest;
    
    /**
     * @author xiaoxu
     * @date 2022-08-30 7:45
     * FruitMall:com.xiaoxu.spiImpl.XiaoxuSpiTestImpl
     */
    public class XiaoxuSpiTestImpl implements XiaoxuSpiTest {
        @Override
        public void spiRun() {
            System.out.println("哈哈哈,我是实现的第一个spi哦");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    package com.xiaoxu.spiImpl;
    
    import com.xiaoxu.spi.XiaoxuSpiTest;
    
    /**
     * @author xiaoxu
     * @date 2022-09-01 7:40
     * FruitMall:com.xiaoxu.spiImpl.XiaoxuSpiUseImpl
     */
    public class XiaoxuSpiUseImpl implements XiaoxuSpiTest {
        @Override
        public void spiRun() {
            System.out.println("我是spi使用的第二个实现~");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    路径如下:
    在这里插入图片描述

    2.2 约定:在resources目录下新建服务接口发现的配置文件

    路径为:src\main\resources\META-INF\services\com.xiaoxu.spi.XiaoxuSpiTest

    配置文件为txt文件,文件名为接口的全限定类名:

    在这里插入图片描述

    文件内容如下,多个实现类,在txt中换行写入即可:

    在这里插入图片描述

    com.xiaoxu.spiImpl.XiaoxuSpiTestImpl
    com.xiaoxu.spiImpl.XiaoxuSpiUseImpl
    
    • 1
    • 2

    2.3 使用服务发现的工具类:ServiceLoader

    package com.xiaoxu.demo;
    
    import com.xiaoxu.spi.XiaoxuSpiTest;
    import org.apache.commons.collections4.CollectionUtils;
    
    import java.util.ServiceLoader;
    
    /**
     * @author xiaoxu
     * @date 2022-08-30 7:47
     * FruitMall:com.xiaoxu.demo.TestSpi
     */
    public class TestSpi {
        @SuppressWarnings(value = "deprecation")
        public static void main(String[] args) {
    
            ServiceLoader<XiaoxuSpiTest> serviceLoader = ServiceLoader.load(XiaoxuSpiTest.class);
    
            CollectionUtils.forAllDo(serviceLoader,(obj)->{
                System.out.println("开始了");
                obj.spiRun();
            });
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    执行结果如下:

    在这里插入图片描述

  • 相关阅读:
    Django基础
    EasyX图形库的下载安装与Dev-C++配置
    代码随想录算法训练营第五十九天| 647.回文子串 、516.最长回文子序列
    Redis基础数据结构及其使用
    一文搞定,JMeter的三种参数化方式
    2023华为杯数学建模D题第三问——区域双碳目标情景设计样例
    2. 工业大数据的特点
    前端技术点滴整理-1
    泛型的使用
    Linux毕业设计:基于OpenCV和QT库实现的人脸识别考勤/门禁系统(arm嵌入式ubuntu)
  • 原文地址:https://blog.csdn.net/a232884c/article/details/126674146