IE盒子

搜索
查看: 218|回复: 1

【未完善】【笔记】Java的SPI机制

[复制链接]

2

主题

9

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2022-9-25 08:51:20 | 显示全部楼层 |阅读模式
参考

https://juejin.cn/post/6844903605695152142
https://cloud.tencent.com/developer/article/1785056
简概

SPI接口的定义在调用方,在概念上更依赖调用方;组织上位于调用方所在的包中;实现位于独立的包中。
接口的实现类需要在classpath下的META-INF/services/目录里创建一个以服务接口命名的文件,文件的内容就是接口的实现类的全类名。
当其他的程序需要这个服务的时候,就可以通过查找这个jar包(一般都是以jar包做依赖)的META-INF/services/中的配置文件,配置文件中有接口的具体实现类名,可以根据这个类名进行加载实例化,就可以使用该服务了。JDK中查找服务实现的工具类是:java.util.ServiceLoader。
应用示例

项目结构





定义接口

package world.shuashua.api;

public interface Service {
    void supportService();
}
定义实现类

package world.shuashua.impl;

import world.shuashua.api.Service;

public class ServiceImpl implements Service {

    public void supportService() {
        System.out.println("由实现类:ServiceImpl 提供服务");
    }
}配置spi文件

在resources目录下新建 META-INF/services 目录,并且在这个目录下新建一个与上述接口的全限定名一致的文件:
注意:这个META-INF/services 目录是写死的约定,在 java.util.ServiceLoader 源码实现中, java.util.ServiceLoader#PREFIX 可以看到这个目录的硬编码。




使用ServiceLoader进行加载

package world.shuashua;

import world.shuashua.api.Service;
import java.util.ServiceLoader;

public class ServiceLoad {
    public static void main(String[] args) {
        ServiceLoader<Service> load = ServiceLoader.load(Service.class);
        load.forEach((service -> {   // 因为实现了Iterable接口,所以有forEach方法
            service.supportService();
            System.out.println(service);
        }));
    }
}
原理

待补充
相关问题


  • SPI重复加载时会创建多个实例吗?
    会的。可以简单测试一下,使用spi加载两次就知道了。
回复

使用道具 举报

3

主题

10

帖子

20

积分

新手上路

Rank: 1

积分
20
发表于 2025-4-19 14:02:27 | 显示全部楼层
支持你哈...................................
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表