SPI 机制-插件化扩展功能
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 {
@Override
public void login() {
System.out.println("使用微信登陆授权");
}
}
定义配置文件
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);
打印结果:
使用微信登陆授权
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 机制-插件化扩展功能的更多相关文章
- ASP.NET MVC 插件化机制
概述 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具 体实 ...
- ASP.NET MVC5 插件化机制简单实现
一.前言 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具体 ...
- 小白也能看懂的插件化DroidPlugin原理(二)-- 反射机制和Hook入门
前言:在上一篇博文<小白也能看懂的插件化DroidPlugin原理(一)-- 动态代理>中详细介绍了 DroidPlugin 原理中涉及到的动态代理模式,看完上篇博文后你就会发现原来动态代 ...
- 在.NET Core中使用简单的插件化机制
前言 插件化,其实也并不是什么新东西了,像nopCommerce等开源项目都有类似的机制,而且功能比较完善和齐全. 相信大家都对接过不少支付方式,支付宝.微信以及各大银行或第三方的支付公司. 我们可以 ...
- ASP.NET:插件化机制
概述 nopCommerce的插件机制的核心是使用BuildManager.AddReferencedAssembly将使用Assembly.Load加载的插件程序集添加到应用程序域的引用中.具体实现 ...
- Android插件化原理解析——Hook机制之动态代理
转自 http://weishu.me/2016/01/28/understand-plugin-framework-proxy-hook/ 使用代理机制进行API Hook进而达到方法增强是框架的常 ...
- 组件化框架设计之Java SPI机制(三)
阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 本篇文章将从深入理解java SPI机制来介绍组件化框架设计: ...
- Java SPI机制:ServiceLoader实现原理及应用剖析
一.背景 SPI,全称Service Provider Interfaces,服务提供接口.是Java提供的一套供第三方实现或扩展使用的技术体系.主要通过解耦服务具体实现以及服务使用,使得程序的可扩展 ...
- Apache DolphinScheduler 2.0.1 来了,备受期待的一键升级、插件化终于实现
✎ 编 者 按:好消息!Apache DolphinScheduler 2.0.1 版本正式发布! 本版本中,DolphinScheduler 经历了一场微内核+插件化的架构改进,70% 的代码被重构 ...
随机推荐
- webpack基础知识
一.基础 1 安装 npm i -g webpack webpack-cli // 推荐安装至本地 npm i -D webpack webpack-cli 2 webpck基础使用 2.1 webp ...
- thinkphp 数据库操作
//所有的数据中,查出某个字段$result = $music->field('music')->select();$hotlist = M('News')->where('stat ...
- git push 出现non-fast-forward的错误
1.git push origin liu_0909:daily_liu_0909 出现non-fast-forward的错误,证明您的本地库跟远程库的提交记录不一致,即 你的本地库版本需要更新2.g ...
- KNN算法实现手写体区分
KNN算法在python里面可以使用pip install指令安装,我在实现之前查看过安装的KNN算法,十分全面,包括了对于手写体数据集的处理.我这里只是实现了基础的识别方法,能力有限,没有数据处理方 ...
- 手写C语言字符库
鉴于以前碰到过很多这样的题目,甚至上次月考核也考了,马上就要考试了,就再重新写一遍,加深印象,但是肯定和库函数有区别,丢失许多细节 1.strlen函数(求字符串长度) int strlen(char ...
- 加深对C#数据类型的认识
值类型: 值类型源于System.Value家族,每个值类型的对象都有一个独立的内存区域用于保存自己的值,值类型 所在的内存区域称之为栈(Stack),只要在代码中修改它,就会在内存区域保存这个值. ...
- netty源码解解析(4.0)-16 ChannelHandler概览
本章开始分析ChannelHandler实现代码.ChannelHandler是netty为开发者提供的实现定制业务的主要接口,开发者在使用netty时,最主要的工作就是实现自己的ChannelHan ...
- Jboss反序列化漏洞复现(CVE-2017-12149)
Jboss反序列化漏洞复现(CVE-2017-12149) 一.漏洞描述 该漏洞为Java反序列化错误类型,存在于jboss的HttpInvoker组件中的ReadOnlyAccessFilter过滤 ...
- 实现万行级excel导出---poi--ooxm的应用和采坑
xl_echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!! - ...
- "A valid provisioning profile for this executable was not found"问题
时间:2015年8月14日 初接触iOS,这两天真机调试的时候遇到了这个问题.如图所示: 上网查后发现,解决方法大致有以下两种: 1. provisioning profile没有被找到,需要重新导入 ...