SPI(Service Provider Interfaces),中文直译服务提供者接口,一种服务发现机制。可能很多人都不太熟悉这个机制,但是平常或多或少都用到了这个机制,比如我们使用 JDBC 连接操作数据库的时候。

SPI 主要适用于功能扩展的场景,如一些框架提供某一部分功能可以由第三方开发人员扩展,满足其自身业务需求。

假设我们在公司内实现了一个统一登陆框架,框架内部仅仅提供用户名/密码登陆方式。后来 A 部门想使用该框架,但是他们想增加微信登陆授权。正常情况下,我们可以改动登陆框架代码,增加微信登陆实现方式。如果后面又增加 QQ 登陆,淘宝登陆那?也只能不断相应的实现。

SPI 实现方式

这种情况如果使用 SPI,可以在不用改动框架代码前提下,增加新的登陆实现方式。下面用代码演示如何使用 SPI。

定义接口

首先我们新建一个 maven 项目 oauth-api,在这个项目创建一个公共接口。

public interface OauthLoginService {void login();
}

第三方实现该接口

再新建一个 maven 项目 wechat-oauth ,引入上面 oauth-api 依赖

public class WechatLoginService implements OauthLoginService {@Overridepublic void login() {System.out.println("使用微信登陆授权");}
}

定义配置文件

SPI 需要将接口实现定义在配置文件中,文件名为接口全名称,如 com.andyxh.OauthLoginService,配置文件需放在 resources\META-INF\services 文件夹下。文件内容如下:

com.another.WechatLoginService

加载接口实现类

新建 maven 项目 oauth-login,在这个项目中引入 wechat-oauthoauth-api 依赖。SPI 核心将会使用 java.util.ServiceLoader读取上面上面定义配置文件,加载所有服务实现类。使用代码如下:


ServiceLoader<OauthLoginService> serviceLoader=ServiceLoader.load(OauthLoginService.class);
serviceLoader.forEach(OauthLoginService::login);

打印结果:

使用微信登陆授权

SPI 实际应用

上面说过 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;  }....}

Java SPI 存在问题

ServiceLoader 一次性将会实例化所有实现,但是如果没有某一扩展初始化耗时很久,但是却不需要立刻使用,就会非常浪费资源。

基于这个问题, Dubbo SPI 机制改进 Java SPI 的不足,做到按需加载并且增加 ioc 与 aop 的功能,下篇文章可以在具体聊聊,敬请期待。

SPI 机制-插件化扩展功能相关推荐

  1. Java SPI机制实现插件化扩展功能

    Java SPI机制实现插件化扩展功能 1.背景 我们有一个图数据库的服务,用户希望在不修改现有源代码的情况下扩展自定义的分词器,达到可插件式扩展功能的目标. 通过Java的SPI机制实现插件式的扩展 ...

  2. Java SPI实现插件化

    SPI 机制使用到很经典的设计原则,在学习之前,首先了解一下: 开闭原则:面向拓展开放,对修改关闭: 里氏替换原则:父类出现的地方都应该可以让子类替换,让子类去增强和扩展功能: 依赖倒置原则:面向接口 ...

  3. 【java】SPI机制详解

    1.概述 以前的文章:[SPI]java基础之SPI框架实现 转载:Java常用机制 - SPI机制详解 PI(Service Provider Interface),是JDK内置的一种 服务提供发现 ...

  4. Android 插件化原理入门笔记

    Android开发笔记 onGithub 笔记,参考7.2中所列参考文章所写,DEMO地址在PluginTestDemoApplication 1.综述 2015年是Android插件化技术突飞猛进的 ...

  5. c++插件化 NDD源码的插件机制实现解析

    插件机制是一种框架,允许开发人员简单地在应用程序中添加或扩展功能.它使广泛使用,因为它可以作为模块被重复使用,并使它们更易于维护和扩展,因此它们在应用程序中非常有用.插件机制允许管理员在需要时轻松安装 ...

  6. Android 插件化原理学习 —— Hook 机制之动态代理

    前言 为了实现 App 的快速迭代更新,基于 H5 Hybrid 的解决方案有很多,由于 webview 本身的性能问题,也随之出现了很多基于 JS 引擎实现的原生渲染的方案,例如 React Nat ...

  7. 平安保险基于 SPI 机制的 RocketMQ 定制化应用

    作者:孙园园|平安人寿资深开发 为什么选用 RocketMQ 首先跟大家聊聊我们为什么会选用 RocketMQ,在做技术选型的过程中,应用场景应该是最先考虑清楚的,只有确定好了应用场景在做技术选型的过 ...

  8. Android插件化原理解析——Hook机制之动态代理

    使用代理机制进行API Hook进而达到方法增强是框架的常用手段,比如J2EE框架Spring通过动态代理优雅地实现了AOP编程,极大地提升了Web开发效率:同样,插件框架也广泛使用了代理机制来增强系 ...

  9. Android 插件化原理解析——Hook机制之AMSPMS

    在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...

  10. android handler的机制和原理_Android 插件化原理——Hook机制之AMSamp;PMS解析

    在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...

最新文章

  1. Linux Wi-Fi 编程API介绍
  2. 【c语言】输入一个4位数,求四位数中各位数相加之和
  3. 大多数的自动驾驶公司,注定要倒闭
  4. PyCharm去掉满屏的波浪线
  5. CFileDialog 在使用sdk 后出现异常 Access violation
  6. 博途pcpg接口无法选择_博途TIA功能,如何创建一个S7-1200的项目及硬件组态?
  7. 沙漠种水稻,88岁的袁隆平又创造奇迹!他参与的“袁米”还有个大计划
  8. java调用MySQL脚本_Java调用SQL脚本执行常用的方法示例
  9. 小鹏N5申报图曝光 搭载155KW电机、NEDC 600公里与P5相同
  10. 游戏社交不足怎么办? 游戏发行中的社交化运营经验分享
  11. paip.跟踪DISCUZ积分日志功能总结
  12. UML入门以及Plant UML工具介绍
  13. 哈尔·埃尔罗德《早起的奇迹》读书笔记
  14. 【Pyecharts50例】一个Tab下添加多个图表/tab.add()
  15. 狗和猫有相同的情绪反应吗?
  16. mongo查询时区转换
  17. windows bat
  18. 马斯克宣布重磅消息!一切来得那么快!
  19. 500天后是几几年几月几日
  20. 记录2015年年初跳槽的经历!

热门文章

  1. nodejs+express中设置登录拦截器
  2. 写了个淡入淡出的jq幻灯片插件
  3. Easyui datagrid加载本地Json数据
  4. 拓端tecdat|R语言随机波动率(SV)模型、MCMC的Metropolis-Hastings算法金融应用:预测标准普尔SP500指数
  5. (3)机器学习_逻辑模型_决策树
  6. Java IO 系统(一)
  7. numpy构建卷积网络
  8. yolov4训练自己的数据
  9. 全卷积网络 FCN 详解
  10. 【深度学习笔记】个人阅读的Deep Learning方向的paper整理