架构设计原则:选择 SPI 还是 API ?

因公众号更改推送规则,请点“在看”并加“星标”第一时间获取精彩技术分享

点击关注#互联网架构师公众号,领取架构师全套资料 都在这里9f49d7f686e0bf7f514fa0e4da8aed0a.png

0、2T架构师学习资料干货分

上一篇:2T架构师学习资料干货分享

大家好,我是互联网架构师!

c6bd7d746e028ac98d4cb26f7e0a63c0.png

背景

087cf7a2760334c00ecd99bfe3d4e6a4.png

第一次听说 SPI 是阅读《软件框架设计的艺术》,以后陆续在 JDBC 和 SpringBoot 中发现了以这种形式组织代码的方式,本位给出为什么要区分 SPI 和 API 的一个思考过程。


085f1ce45b3db590e4f8c0ebea631c97.png

从面向接口编程说起

f92ce4b91390baa2083fcdf10d5bbfaa.png

6cfc0ce6eb20b7583dda663c03168807.jpeg

我们在“调用方”和“实现方”之间引入了“接口”,上图没有给出“接口”应该位于哪个“包”中,从纯粹的可能性上考虑,我们有三种选择:

  1. “接口”位于“调用方”所在的“包”中。

  2. “接口”位于“实现方”所在的“包”中。

  3. “接口”位于独立的“包”中。

下面让我们依次分析这三种可能性,如果现实中确实有这种可能性,不如我们就为其起个名字以方便交流。


eca5066a954e6555bf2a2ab9d31d55d4.png

“接口”位于“调用方”所在的“包”中

28654cc0ce66801520d5a3eecdca9ae5.png

我们先想象一个场景,以仓储的接口为例:

1be0f3a6b9abdeb6a5661a1a0fb2061c.jpeg

我们将“仓储接口”放置于“领域层”这个“包”中,实现放在一个独立的“包”中,我们看DDD大师的实现都是这样子,现在来思考一下为什么这么做。

“领域层”的“领域服务”会依赖“仓储接口”,“仓储接口”也会依赖“聚合根”,这两者都是除了“实现依赖”之外的依赖关系,如果将“接口”放到“仓储实现”中就丧失了面向接口编程的意义(编译也不会通过),如果放到“独立层”中呢?会编译不通过,出现双向依赖了。

对于类似这种情况下接口,我们将其称为“SPI”,全程为:service provider interface,“SPI”的规则如下:

  1. 概念上更依赖调用方。

  2. 组织上位于调用方所在的包中。

  3. 实现位于独立的包中。

  4. 常见的例子是:插件模式的插件。


660d82963fd6731476035f8fc1f22366.png

“接口”位于“实现方”所在的“包”中

747ef96fa890aa5ab7e71b5e33d377a0.png

我们先想象一个场景,以Unity提供的IUnityContainer接口为例,除了维护这个框架的团队之外,我们没有发现谁实现了这个接口,虽然理论上是可以实现这个接口的(如果能实现的话,我们何不自己弄额Ioc容器呢?)。

对于类似这种情况下的接口,我们将其称作为“API”,“API”的规则如下:

  1. 概念上更接近实现方。

  2. 组织上位于实现方所在的包中。

  3. 实现和接口在一个包中。


ce230f17eda21637ceabbb623228fcd2.png

“接口”位于独立的“包”中

4bc037d41c6cd4bc9a651024de7f1ac7.png

这里就不说场景了,如果一个“接口”在一个上下文是“API”,在另一个上下文是“SPI”,那么你就可以这么组织。


ad390aed7c313ae68f9fb10be499b04a.png

需要注意的事项

2e0e6d946eb65b6d9557cb029f804751.png

不管是 SPI 或 API,接口都是可以组织到独立的“包”中,这么做是否有意义,自己来做出决定了。

SPI 和 API 也不一定是接口,我这里都是指狭义的具体的接口。


deed5142f53d544ca5e019af6093aea5.png

场景图

7298e85c5d746c859e766cf64bc74fd4.png

9c042db1e5b99cc2dfbd46ca81d43295.jpeg

每一次思考都伴随着收获,也离不开和朋友们的交流,天更蓝了。

SPI 接口:

  1. 定义:SPI 是一种服务提供者接口,它允许在运行时加载不同的服务实现。

  2. 使用场景

  • 模块化设计:当系统需要高度模块化,且希望将核心功能与具体实现分离时。

  • 可插拔架构:需要支持多种服务实现,并且可以在不修改代码的情况下替换或增加新的服务实现。

  • 服务发现:在运行时根据配置或服务注册表动态发现和加载服务。

  • 微服务架构:在微服务架构中,SPI 可用于服务间的动态交互和集成。

优点

  • 提供了一种机制来在运行时选择和加载服务实现,增加了系统的灵活性和可扩展性。

  • 支持服务的热插拔,无需重启系统即可更换服务实现。

API 接口:

  1. 定义:API 是一组预定义的函数、协议和工具,用于构建软件应用,它定义了软件组件之间交互的契约。

  2. 使用场景

  • 客户端和服务器交互:当需要设计客户端和服务器之间的通信协议时。

  • 库和框架:提供给开发者使用的库或框架的公共接口。

  • 第三方集成:需要与第三方系统或服务进行集成。

  • 内部组件通信:在大型系统中,不同组件或模块之间的交互。

优点

  • 为开发者提供了清晰的接口文档和规范,易于理解和使用。

  • 有助于保持系统的稳定性,因为 API 变更需要遵循版本控制和兼容性规则。

  • 促进了代码的重用和模块化。

如何选择?

选择使用 SPI 还是 API 的考虑因素:

  • 扩展性:如果需要在不修改代码的情况下扩展功能,SPI 更合适。

  • 交互性:API 更适合定义系统内部或系统之间的稳定交互接口。

  • 动态性:SPI 允许在运行时动态发现和加载服务,而 API 通常在编译时就已经确定。

  • 安全性和稳定性:API 由于其稳定性和可预测性,通常更受青睐。SPI 虽然灵活,但可能引入运行时错误。

  • 版本控制和兼容性:API 变更需要考虑版本控制和向后兼容性,而 SPI 可以通过服务版本协商来处理兼容性问题。

架构是“取舍”,而非“银弹”。

作者:幸福框架

来源:www.cnblogs.com/happyframework/p/3325560.html

—  —

如喜欢本文,请点击右上角,把文章分享到朋友圈

1、2T架构师学习资料干货分享

2、10000+TB 资源,阿里云盘,牛逼!!

3、基本涵盖了Spring所有核心知识点总结

  · END ·

最后,关注公众号互联网架构师,在后台回复:2T,可以获取我整理的 Java 系列面试题和答案,非常齐全。

如果这篇文章对您有所帮助,或者有所启发的话,帮忙扫描上方二维码关注一下,您的支持是我坚持写作最大的动力。

求一键三连点赞、转发、在看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值