SPI (Service Provider Interfaces), 中文直译服务提供者接口,一种服务发现机制。可能不少人都不太熟悉这个机制,可是日常或多或少都用到了这个机制,好比咱们使用 JDBC 链接操做数据库的时候。java
SPI 主要适用于功能扩展的场景,如一些框架提供某一部分功能能够由第三方开发人员扩展,知足其自身业务需求。mysql
假设咱们在公司内实现了一个统一登录框架,框架内部仅仅提供用户名 / 密码登录方式。后来 A 部门想使用该框架,可是他们想增长微信登录受权。正常状况下,咱们能够改动登录框架代码,增长微信登录实现方式。若是后面又增长 QQ 登录,淘宝登录那?也只能不断相应的实现。sql
这种状况若是使用 SPI,能够在不用改动框架代码前提下,增长新的登录实现方式。下面用代码演示如何使用 SPI。数据库
定义接口api
首先咱们新建一个 maven 项目 oauth-api
,在这个项目建立一个公共接口。微信
public interface OauthLoginService { void login(); }
第三方实现该接口框架
再新建一个 maven 项目 wechat-oauth
,引入上面 oauth-api
依赖maven
public class WechatLoginService implements OauthLoginService { @Override public void login() { System.out.println("使用微信登录受权"); } }
定义配置文件ide
SPI 须要将接口实现定义在配置文件中,文件名为接口全名称,如 com.andyxh.OauthLoginService
,配置文件需放在 resources\META-INF\services 文件夹下。文件内容以下:插件
com.another.WechatLoginService
加载接口实现类
新建 maven 项目 oauth-login
, 在这个项目中引入 wechat-oauth
与 oauth-api
依赖。SPI 核心将会使用 java.util.ServiceLoader
读取上面上面定义配置文件,加载全部服务实现类。使用代码以下:
ServiceLoader<OauthLoginService> serviceLoader=ServiceLoader.load(OauthLoginService.class); serviceLoader.forEach(OauthLoginService::login);
打印结果:
使用微信登录受权
上面说过 JDBC 中使用到 SPI 进制。JDK 定义标准数据库接口,相应的数据库厂商实现这类接口。以 mysql-connector-javal
为例。
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency>
mysql jar 包 META-INF/services 中存在 java.sql.Driver
文件,这个文件定义了实现类。
com.mysql.cj.jdbc.Driver
能够看到 java.sql.Driver
是标准 SPI 接口,而 com.mysql.cj.jdbc.Driver
是 mysql 标准实现接口。
什么时候加载 java.sql.Driver
?
咱们将会使用 DriverManager.getConnection
获取相应数据库链接。这个类内部存在一个静态代码块,将会使用 ServiceLoader
加载实现类。
static { loadInitialDrivers(); println("JDBC DriverManager initialized"); } private static void loadInitialDrivers() { .... ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class); Iterator<Driver> driversIterator = loadedDrivers.iterator(); try{ while(driversIterator.hasNext()) { driversIterator.next(); } } catch(Throwable t) { // Do nothing } return null; } .... }
ServiceLoader
一次性将会实例化全部实现,可是若是没有某一扩展初始化耗时好久,可是却不须要马上使用,就会很是浪费资源。
基于这个问题, Dubbo SPI 机制改进 Java SPI 的不足,作到按需加载而且增长 ioc 与 aop 的功能,下篇文章能够在具体聊聊,敬请期待。