您当前的位置: 首页 >  Java

Charge8

暂无认证

  • 4浏览

    0关注

    430博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Java SPI机制

Charge8 发布时间:2022-07-10 14:02:08 ,浏览量:4

一、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 serviceLoader = ServiceLoader.load(MyLog.class);

        //遍历所有实现类
        Iterator 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会一次性实例化扩展点的所有实现。

参考文章:

  • SPI机制是什么?:https://blog.csdn.net/ymb615ymb/article/details/123450610

– 求知若饥,虚心若愚。

关注
打赏
1661954522
查看更多评论
立即登录/注册

微信扫码登录

0.1057s