Java SPI机制

5 篇文章 0 订阅

一、SPI机制简介

1、什么是SPI机制

SPI(Service Provider Interface 的简称)字面意思为服务提供者接口,它是 JDK内置的一种服务提供发现机制(JDK提供给“服务提供厂商”或者“插件开发者”使用的接口)。

SPI是一种动态替换发现的扩展机制制,一种解耦非常优秀的思想。它可以很灵活的让接口和实现分离, 让api提供者只提供接口, 第三方来实现。

SPI机制的主要目的:

  • 为了解耦,将接口和具体实现分离开来;
  • 提高框架的扩展性。

1.1 Java SPI规范

定义服务的通用接口,针对通用的服务接口,提供具体的实现类。

  1. 在jar包(服务提供者)的 META-INF/services/目录 中,新建一个文件,
    • 文件名为SPI接口的"全限定名"
    • 文件内容为该接口的具体实现类的"全限定名"
  2. 将spi所在jar放在主程序的classpath中。
  3. 服务调用方使用 java.util.ServiceLoader去动态加载具体的实现类到JVM中。

Java SPI的工作原理:

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

2、优缺点

优点:

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

缺点:

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

二、如何使用Java的SPI

1、自定义接口和实现类

1.1 接口

public interface MyLog {
    void debug();
}

1.2 实现类

这里定义两个实现类。

public class MyLog4j implements MyLog {
    @Override
    public void debug() {
        System.out.println("==========MyLog4j");
    }
}

public class MyLogback implements MyLog {
    @Override
    public void debug() {
        System.out.println("==========MyLogback");
    }
}

2、创建配置文件

在项目resources目录下新建一个 META-INF/services文件夹

  • 在 META-INF/services/目录下,创建一个文件,文件名为该SPI接口的全限定名
  • 文件内容是具体实现类的全限定名,如果有多个,则用分行符分隔。

在这里插入图片描述

3、测试,加载实现类

在 代码中通过使用 java.util.ServiceLoader来动态加载具体的实现类并实例化到JVM中。

public class MySpiTest {

    public static void main(String[] args) {
        //加载META-INF/services 下面的MyLog文件中的所有实现类
        ServiceLoader<MyLog> serviceLoader = ServiceLoader.load(MyLog.class);

        //遍历所有实现类
        Iterator<MyLog> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            MyLog next = iterator.next();
            if(next instanceof MyLog) {
                next.debug();
            }else if(next instanceof MyLogback) {
                next.debug();
            }else {
                System.out.println("其他");
            }
        }
    }
}

在这里插入图片描述

注意:JDK SPI会一次性实例化扩展点的所有实现。

参考文章:

– 求知若饥,虚心若愚。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值