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();
}

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

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哦");
    }
}
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使用的第二个实现~");
    }
}

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

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

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

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

在这里插入图片描述

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

在这里插入图片描述

com.xiaoxu.spiImpl.XiaoxuSpiTestImpl
com.xiaoxu.spiImpl.XiaoxuSpiUseImpl

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();
        });
    }
}

执行结果如下:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值