Java的SPI机制是什么
一、介绍
大家有没有遇到过这么一个神奇的现象,在Java
中,我们引入了什么日志就会用到什么日志,
比如说,我引入了logback
,那么日志打印就会使用logback
引入了log4j
,那么就会使用log4j
演示就不进行了,但这是怎么做到的呢?
实际上,它正是使用了Java
的SPI
机制
SPI
机制,是Service Provider Interface
的缩写,字面意思就是服务提供者的接口。
详细描述就是,一个框架提供暴露出一个接口,交给外部第三方去完成具体的实现。框架不需要关系是谁,哪些类实现了这个接口,只需要调用这个接口的方法,完成功能即可。
按照这么说,日志框架应该就是这个样子。有一个接口提供出去,不同的框架去实现这个接口,到时候maven
依赖引入,就自动的加载成功。
好的,那下面我们来自己手动写一个SPI
的代码,加深一点印象
二、代码
1)接口及扩展
同介绍中说的,我们先提供一个接口,我把它放在learn-spi-core
工程下边,这个接口里面就一个方法
package com.banmoon;
/**
* SPI测试接口
*
* @author banmoon
* @date 2024/08/09 13:59:38
*/
public interface BaseExecutor {
/**
* 执行
*/
void execute();
}
那么,我另开一个工程,learn-spi-extend-a
,去写一个实现类
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
,文件名正好就是上面提供的接口权限名,里面放上自己实现类的权限名
com.banmoon.ExtendExecutorA
2)测试一下
直接再开一个工程learn-spi-main
,maven
引入相关依赖
<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
方法
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
,同样的实现
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
依赖加入上去
<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
方法代码不用动,执行运行,可以看到两个都出来了
四、最后
代码比较简单,但就是这样的一个机制,可以完成框架神奇一般的功能
附上本次,项目的工程结构图