SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一种动态替换发现的机制,我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。 某个接口,想运行时动态的给它添加实现,你只需要添加一个实现。例如: 数据库驱动,dubbo都使用了这种机制。
具体是在JAR包的"resources/META-INF/services/"目录下建立一个文件,文件名是接口的全限定名,文件的内容可以有多行,每行都是该接口对应的具体实现类的全限定名。
示例项目结构如下:
package com.springboot.spi; /** * @Title: Driver * @Description: spi 接口 * @author chy * @date 2018/6/25 13:43 */ public interface Driver { public void sayHello(); }
/** * @Title: JsonDriver * @Description: json 驱动实现 * @author chy * @date 2018/6/25 13:45 */ public class JsonDriver implements Driver { @Override public void sayHello() { System.out.println("JsonDriver"); } }
/** * @Title: XmlDriver * @Description: xml 驱动实现 * @author chy * @date 2018/6/25 13:46 */ public class XmlDriver implements Driver { @Override public void sayHello() { System.out.println("XmlDriver"); } }
resources/META-INF/services/ 目录中建立 com.springboot.spi.Driver 文件,内容如下:
com.springboot.spi.JsonDriver com.springboot.spi.XmlDriver
/** * @Title: DemoSpiTest * @Description: spi 测试 * @author chy * @date 2018/6/25 13:49 */ @RunWith(SpringRunner.class) @SpringBootTest public class DemoSpiTest { @Test public void run() { ServiceLoader<Driver> matcher = ServiceLoader.load(Driver.class); Iterator<Driver> matcherIter = matcher.iterator(); while (matcherIter.hasNext()) { Driver driver = matcherIter.next(); System.out.println(driver.getClass().getName()); driver.sayHello(); } } }
控制台输出:
com.springboot.spi.JsonDriver
JsonDriver
com.springboot.spi.XmlDriver
XmlDriver