最近在看dubbo源码,了解到spi机制,其实之前有了解,只是没有花时间去弄清楚
网上看到很多将spi跟api对比,spi就像给浏览器装插件,浏览器预留了接口,按照这个接口规范去开发插件即可
很多spi的demo都是定义一个service,然后写两个实现serviceA,serviceB并将其添加到META-INF/services目录文本文件下,然后通过ServiceLoader获取实例,然而这样看不到其明显的优点及作用。
我们接触的与spi相关的应用场景主要有数据库driver及日志LogFactory,因此写个模拟数据库driver加载的spi实例来帮助理解
代码结构如下:
主要代码逻辑有
DriverManager中静态块触发ServiceLoader去实例化类
static {
loadInitialDrivers();
}
private static void loadInitialDrivers() {
ServiceLoader loadeDrivers = ServiceLoader.load(CustomDriver.class);
Iterator driverIterator = loadeDrivers.iterator();
while (driverIterator.hasNext()) {
driverIterator.next();
}
}
Driver将自身注册到DriverManager
static {
CustomDriverManager.registerDriver(new CustomDriver());
}
记得原来连接mysql经常见到Class.forName("com.mysql.jdbc.Driver"),那时只知道这样写才行,不知道为什么一定要这么写
这句话的主要目的是初始化类,执行其static块,将其Driver添加到DriverManager中;但现在通过spi来自动扫描创建对象已包含了初始化过程,
因此现在连接mysql数据库,实质上是不需要这句了的
demo代码地址:https://github.com/ticsmtc6/spi-demo
个人理解:spi是非必须的,实质上如果服务不是很复杂,预期不是经常添加扩展的话,用spring配置两个服务更简单