前言
什么是SPI?SPI 的全称 Service Provider Interface,是 Java 提供的一套用来被第三方实现或者扩展的 API,机制如下图:
如何使用
要使用 Java SPI,需要遵循下面的几点约定:
- 当服务提供者提供了接口的一种具体实现后,在 jar 包的 META-INF/services 目录下创建一个以“接口全限定名”为命名的文件,内容为实现类的全限定名;
- 接口实现类所在的 jar 包放在主程序的 classpath 中;
- 主程序通过 java.util.ServiceLoder 动态装载实现模块,扫描 META-INF/services 目录下的配置文件找到实现类的全限定名,把类加载到 JVM;
- SPI的实现类必须携带一个不带参数的构造方法;
示例
- 首先定义好接口
public interface DataSourceSpi { /** * 连接方法 * @param urlName */ void connection(String urlName); }
- 定义两个实现类
public class MysqlDataSource implements DataSourceSpi { public void connection(String urlName) { System.out.println("MySQL Connection url:" + urlName); } } public class OracleDataSource implements DataSourceSpi { public void connection(String urlName) { System.out.println("Oracle Connection url:" + urlName); } }
- 然后在 src 下新建 resources 包,按约定新建好 META-INF/services 文件夹,再新建一个定义好接口的全限定类名的文件,我这里是 com.zenglh.spi.DataSourceSpi。
- 新建完文件后,在类里面把实现类的全限定类名写上,每个类一行:
com.zenglh.spi.impl.MysqlDataSource com.zenglh.spi.impl.OracleDataSource
- 最后新建一个测试类,来测试一下是否成功
如果输出来下面这样的,就说明成功了public class SpiMain { public static void main(String[] args) { ServiceLoader<DataSourceSpi> dataSourceSpis = ServiceLoader.load(DataSourceSpi.class); for (DataSourceSpi spi : dataSourceSpis) { spi.connection("10.xxx.xxx.xxx:3306"); } } }
总结
JDK 中原生的 Spi 只要按照约定的地方配置好,然后就可以使用了,后续再写一往篇自己实现的 Spi。