Java 中的 SPI

SPI全名为Service Provider Interface

系统设计的各个抽象,往往有很多不同的实现方案,在面向的对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制
Java SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。所以SPI的核心思想就是解耦

简单实现SPI思想

在这里插入图片描述
java-spi<pom.xml>

    <artifactId>java-spi</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>service-common</module>
        <module>ali-pay</module>
        <module>wx-pay</module>
        <module>main-test</module>
    </modules>

提供服务接口
在这里插入图片描述

public interface PayService {
    public void pay();
}

ali-pay、wx-pay分别给予实现
在这里插入图片描述
ali-pay<pom.xml>

    <dependencies>
        <dependency>
            <artifactId>service-common</artifactId>
            <groupId>com.ff</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
public class AliPay implements PayService {
    @Override
    public void pay() {
        System.out.println("支付宝支付");
    }
}

在这里插入图片描述

wx-pay<pom.xml>

    <dependencies>
        <dependency>
            <artifactId>service-common</artifactId>
            <groupId>com.ff</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
public class WXPay implements PayService {
    @Override
    public void pay() {
        System.out.println("微信支付");
    }
}

测试
在这里插入图片描述
ServiceLoader:一个简单的服务提供商加载工具。(具体可查API)
此时打印控制台打印肯定是什么都没有的,因为我们还没有加载具体服务

public class MainTest {

    public static void main(String[] args) {
        ServiceLoader<PayService> load = ServiceLoader.load(PayService.class);
        for (PayService payService : load) {
            System.out.println(payService);
        }
    }
}

来看看ServiceLoader
在这里插入图片描述
按照规范创建文件
在这里插入图片描述
在这里插入图片描述
wx-pay同理
在这里插入图片描述
在这里插入图片描述
main-test还需要添加相关依赖

    <dependencies>
        <dependency>
            <artifactId>service-common</artifactId>
            <groupId>com.ff</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.ff</groupId>
            <artifactId>ali-pay</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.ff</groupId>
            <artifactId>wx-pay</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

此时测试,服务就可以得到具体的实现
在这里插入图片描述

Java SPI 规范

  1. 当服务提供者提供了接口的一种具体实现后,在 jar 包的 META-INF/services 目录下创建一个以“接口全路径名”为命名的文件,内容为实现类的全限定名;
  2. 接口实现类所在的 jar 包放在主程序的 classpath 中;
  3. 主程序通过 java.util.ServiceLoder 动态装载实现模块,它通过扫描 META-INF/services目录下的配置文件找到实现类的全限定名,把类加载到 JVM;
  4. SPI 的实现类必须携带一个不带参数的构造方法;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值