什么是SPI

SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。 Java SPI 实际上是“ 基于接口的编程+策略模式+配置文件 ”组合实现的动态加载机制。 系统设计的各个抽象,往往有很多不同的实现方案,在面向的对象的设计里,一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。

SPI与策略模式的区别【2】

从代码层面看,策略模式还是在原有项目中进行代码修改,只是不会修改原有类的代码,而是新建类;SPI机制是不会修改原有项目中代码,其会新建一个项目,最终以Jar包引入的方式代码(当然在同个项目中也是可以的)
两者目的都是解耦,但策略模式只能在类层次上做隔离,更适合在业务代码领域;而SPI机制更多则是框架的设计领域,通过SPI机制提供的灵活性,让框架拥有良好的插件特性,便于扩展

SPI与API区别

Java程序员常常是面向接口编程,SPI与面向接口编程是紧密相关的。简单地说,如果一个接口由调用方来定义而接口实现由提供方实现,这个就是SPI;如果接口的定义和实现都由提供方完成,就是我们常说的API
SPI(Service Provider Interface)服务提供接口,简单来说就是用来解耦,实现插件的自由插拔,具体实现方案可参考JDK里的ServiceLoader(加载classpath下所有META-INF/services/目录下的对应给定接口包路径的文件,然后通过反射实例化配置的所有实现类,以此将接口定义和逻辑实现分离)

Example

SPI机制是加载classpath下所有META-INF/services/目录下的对应给定接口包路径的文件。demo中加载的是per.java.basic.example.spi.Search接口,故文件名称也是per.java.basic.example.spi.Search,文件内容是该接口的实现类
image.png
接口类

  1. package per.java.basic.example.spi;
  2. import java.util.List;
  3. public interface Search {
  4. public List<String> doSearch(String keyword);
  5. }

实现类1:DataBaseSearch

  1. package per.java.basic.example.spi.impl;
  2. import per.java.basic.example.spi.Search;
  3. import java.util.List;
  4. public class DataBaseSearch implements Search {
  5. @Override
  6. public List<String> doSearch(String keyword) {
  7. System.out.println("implement by database");
  8. return null;
  9. }
  10. }

实现类2:FileSearch

  1. package per.java.basic.example.spi.impl;
  2. import per.java.basic.example.spi.Search;
  3. import java.util.List;
  4. public class FileSearch implements Search {
  5. @Override
  6. public List<String> doSearch(String keyword) {
  7. System.out.println("implement by file");
  8. return null;
  9. }
  10. }

image.png

参考

【1】https://zhuanlan.zhihu.com/p/28909673
【2】https://www.cnblogs.com/chanshuyi/p/the_difference_between_spi_and_strategy.html