前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java的SPI机制是什么

Java的SPI机制是什么

原创
作者头像
半月无霜
发布2024-08-10 18:58:59
810
发布2024-08-10 18:58:59
举报
文章被收录于专栏:半月无霜

Java的SPI机制是什么

一、介绍

大家有没有遇到过这么一个神奇的现象,在Java中,我们引入了什么日志就会用到什么日志,

比如说,我引入了logback,那么日志打印就会使用logback

引入了log4j,那么就会使用log4j

演示就不进行了,但这是怎么做到的呢?

实际上,它正是使用了JavaSPI机制

SPI机制,是Service Provider Interface的缩写,字面意思就是服务提供者的接口。

详细描述就是,一个框架提供暴露出一个接口,交给外部第三方去完成具体的实现。框架不需要关系是谁,哪些类实现了这个接口,只需要调用这个接口的方法,完成功能即可。

按照这么说,日志框架应该就是这个样子。有一个接口提供出去,不同的框架去实现这个接口,到时候maven依赖引入,就自动的加载成功。

好的,那下面我们来自己手动写一个SPI的代码,加深一点印象

二、代码

1)接口及扩展

同介绍中说的,我们先提供一个接口,我把它放在learn-spi-core工程下边,这个接口里面就一个方法

代码语言:javascript
复制
package com.banmoon;
​
/**
 * SPI测试接口
 *
 * @author banmoon
 * @date 2024/08/09 13:59:38
 */
public interface BaseExecutor {
​
    /**
     * 执行
     */
    void execute();
​
}

那么,我另开一个工程,learn-spi-extend-a,去写一个实现类

代码语言:javascript
复制
package com.banmoon;
​
/**
 * @author banmoon
 * @date 2024/08/09 14:05:07
 */
public class ExtendExecutorA implements BaseExecutor  {
    @Override
    public void execute() {
        System.out.println("扩展A");
    }
}

十分简单,就打印了一句话

关键来了,实现SPI机制的关键就是要在resources中添加这么一个文件夹,META-INF.services

里面新增这么一个文件com.banmoon.BaseExecutor,文件名正好就是上面提供的接口权限名,里面放上自己实现类的权限名

代码语言:javascript
复制
com.banmoon.ExtendExecutorA

2)测试一下

直接再开一个工程learn-spi-mainmaven引入相关依赖

代码语言:javascript
复制
<dependencies>
    <dependency>
        <groupId>com.banmoon</groupId>
        <artifactId>learn-spi-core</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>com.banmoon</groupId>
        <artifactId>learn-spi-extend-a</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

就在这个工程下面,编写main方法

代码语言:javascript
复制
package com.banmoon;
​
import java.util.ServiceLoader;
​
/**
 * @author banmoon
 * @date 2024/08/09 15:41:11
 */
public class Main {
​
    public static void main(String[] args) {
        ServiceLoader<BaseExecutor> load = ServiceLoader.load(BaseExecutor.class);
        for (BaseExecutor executor : load) {
            executor.execute();
        }
    }
​
}

运行查看效果,可以发现明明没有实例化的动作,但确实有打印输出

三、再次扩展

那么本次,我们再添加一个工程learn-spi-extend-b,同样的实现

代码语言:javascript
复制
package com.banmoon;
​
/**
 * @author banmoon
 * @date 2024/08/09 14:05:07
 */
public class ExtendExecutorB implements BaseExecutor  {
    @Override
    public void execute() {
        System.out.println("扩展B");
    }
}

同样的在META-INF.services加入文件

测试之前,我们将maven依赖加入上去

代码语言:javascript
复制
<dependencies>
    <dependency>
        <groupId>com.banmoon</groupId>
        <artifactId>learn-spi-core</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>com.banmoon</groupId>
        <artifactId>learn-spi-extend-a</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>com.banmoon</groupId>
        <artifactId>learn-spi-extend-b</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

main方法代码不用动,执行运行,可以看到两个都出来了

四、最后

代码比较简单,但就是这样的一个机制,可以完成框架神奇一般的功能

附上本次,项目的工程结构图

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java的SPI机制是什么
    • 一、介绍
      • 二、代码
        • 1)接口及扩展
        • 2)测试一下
      • 三、再次扩展
        • 四、最后
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档