初识SPI

前言

先不深究机制及原理,仅是认识SPI是如何生效的。

  1. 定义1个接口
1
2
3
4
5
6
/**
* @author cuishiying
* @date 2021-01-22
*/
public interface IAlgorithm {
}
  1. 实现类
1
2
3
4
5
6
/**
* @author cuishiying
* @date 2021-01-22
*/
public class LoopAlgorithm implements IAlgorithm {
}
1
2
3
4
5
6
/**
* @author cuishiying
* @date 2021-01-22
*/
public class RandomAlgorithm implements IAlgorithm {
}
  1. 在resources下创建目录 META-INF/services/, 并在目录下新建全路径接口文件
1
2
3
4
5
➜  services pwd
/Users/cuishiying/work/examples/demo-java/src/main/resources/META-INF/services
➜ services tree
.
└── com.example.clz.IAlgorithm
  1. 在接口中定义实现类
1
2
com.example.clz.LoopAlgorithm
com.example.clz.RandomAlgorithm
  1. 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Slf4j
public class Main {

/**
* 15:17:12.924 [main] INFO com.example.clz.Main - 接口实现类: com.example.clz.LoopAlgorithm
* 15:17:12.931 [main] INFO com.example.clz.Main - 接口实现类: com.example.clz.RandomAlgorithm
*/
public static void main(String[] args) {
ServiceLoader<IAlgorithm> serviceLoader = ServiceLoader.load(IAlgorithm.class);
for (IAlgorithm algorithm : serviceLoader){
log.info("接口实现类: {}", algorithm.getClass().getName());
}
}
}
  1. 应用场景

知道什么场景适合使用xx技术, 学习的技术才有意义。比如我们想做个平台,扩展功能通过插件提供, 那么SPI就可以应用,平台定义接口。插件jar中引用接口jar并做具体实现,然后插件通过SPI配置即可在平台主程序中得到执行。

eg: 公司自定义框架中, 配置文件的读取通过ServiceLoader.load加载, 我们可以实现基于zk、nacos等多种实现, 按需依赖即可