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% 的代码被重构 ...
随机推荐
- http面试笔试常考知识点(一)
1.什么是http HTTP是客户端和服务器端请求和应答的标准.通过使用Web浏览器.网络爬虫或者其它的工具,客户端发起一个到服务器上指定端口(默认端口为80)的HTTP请求.(我们称这个客户端)叫用 ...
- Python基础之格式化输出、运算符、数字与布尔值互换以及while...else
python是一天学一点,就这样零零碎碎…… 格式化输出 %是占位符,%s是字符串格式,%d整数格式,%f是浮点数格式 name = input('输入姓名') age = input('输入年龄') ...
- ThinkPHP5.0 模板
ThinkPHP5.0 模板 模板渲染 默认的视图目录是默认的模块下的view目录 渲染规则:调用 \think\View 类fetch方法 // [模板文件目录]/当前控制器名(小写+下划线)/当前 ...
- mysql8.0.15创建数据库和是删除数据库及用户删除
1.首先安装mysql8.0.15 2.Mysql8.0.15安装成功后,默认的root用户密码为空,用以下命令来登录root用户: mysql –u root –p 记住密码不用输入 3.进入之后修 ...
- linux初学者-磁盘加密篇
linux初学者-磁盘加密篇 因为保密需要,一般系统中会在文件和磁盘中进行加密,但是文件的加密比较容易破解,不安全.所以在特殊需要下,会对磁盘进行加密,磁盘加密后在磁盘损坏的同时,其中的数据也会损坏, ...
- Python生成器和构造器
什么是生成器? 参考link:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00 ...
- docker环境下使用gitlab,gitlab-runner 为 NetCore 持续集成
环境 Centos7.6 安装应用docker,docker-compose (我的Centos是用Hyper-V跑的分了8G的内存,阿里云2G根本跑不起来gitlab) 为了保证我的Centos环境 ...
- module中module.exports与exports的区别(转)
转https://cnodejs.org/topic/55ccace5b25bd72150842c0a require 用来加载代码,而 exports 和 module.exports 则用来导出代 ...
- 03-k8s认证
目录 k8s认证 客户端 ---> API Server 外部访问 pod 客户端 RBCA k8s 用户类型 dashboard 的认证登录 k8s认证 主要使用 RBAC授权检查机制 认证: ...
- 浅谈 ASCII、Unicode、UTF-8,一目了然
对于ASCII.Unicode.UTF-8这三种编码方式我们经常用到,也经常挂到嘴边,但他们是怎么来的,为什么要存在,具体是怎么个规则,我们并没有做深入了解,下面,就带你看一下他们到底是怎么回事吧…… ...