当前位置: 首页 > news >正文

Dubbo 源码分析 – SPI 机制

1.简介

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口 加载实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。下面,我们先来了解一下 Java SPI 与 Dubbo SPI 的使用方法,然后再来分析 Dubbo SPI 的源码。

2.SPI 示例

2.1 Java SPI 示例

前面简单介绍了 SPI 机制的原理,本节通过一个示例来演示 JAVA SPI 的使用方法。首先,我们定义一个接口,名称为 Robot。

public interface Robot {void sayHello();
}

接下来定义两个实现类,分别为擎天柱 OptimusPrime 和大黄蜂 Bumblebee。

public class OptimusPrime implements Robot {@Overridepublic void sayHello() {System.out.println("Hello, I am Optimus Prime.");}
}public class Bumblebee implements Robot {@Overridepublic void sayHello() {System.out.println("Hello, I am Bumblebee.");}
}

接下来 META-INF/services 文件夹下创建一个文件,名称为 Robot 的全限定名 com.tianxiaobo.spi.Robot。文件内容为实现类的全限定的类名,如下:

com.tianxiaobo.spi.OptimusPrime
com.tianxiaobo.spi.Bumblebee

做好了所需的准备工作,接下来编写代码进行测试。

public class JavaSPITest {@Testpublic void sayHello() throws Exception {ServiceLoader<Robot> serviceLoader = ServiceLoader.load(Robot.class);System.out.println("Java SPI");serviceLoader.forEach(Robot::sayHello);}
}

最后来看一下测试结果,如下:

从测试结果可以看出,我们的两个实现类被成功的加载,并输出了相应的内容。关于 Java SPI 的演示先到这,接下来演示 Dubbo SPI。

2.2 Dubbo SPI 示例

Dubbo 并未使用 Java SPI,而是重新实现了一套功能更强的 SPI 机制。Dubbo SPI 的相关逻辑被封装在了 ExtensionLoader 类中,通过 ExtensionLoader,我们可以加载指定的实现类。Dubbo SPI 的实现类配置放置在 META-INF/dubbo 路径下,下面来看一下配置内容。

optimusPrime = com.tianxiaobo.spi.OptimusPrime
bumblebee = com.tianxiaobo.spi.Bumblebee

与 Java SPI 实现类配置不同,Dubbo SPI 是通过键值对的方式进行配置,这样我们就可以按需加载指定的实现类了。另外,在测试 Dubbo SPI 时,需要在 Robot 接口上标注 @SPI 注解。下面来演示一下 Dubbo SPI 的使用方式:

public class DubboSPITest {@Testpublic void sayHello() throws Exception {ExtensionLoader<Robot> extensionLoader = ExtensionLoader.getExtensionLoader(Robot.class);Robot optimusPrime = extensionLoader.getExtension("optimusPrime");optimusPrime.sayHello();Robot bumblebee = extensionLoader.getExtension("bumblebee");bumblebee.sayHello();}
}

测试结果如下:

演示完 Dubbo SPI,下面来看看 Dubbo SPI 对 Java SPI 做了哪些改进,以下内容引用至 Dubbo 官方文档。

  • JDK 标准的 SPI 会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。
  • 如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK 标准的 ScriptEngine,通过 getName() 获取脚本类型的名称,但如果 RubyScriptEngine 因为所依赖的 jruby.jar 不存在,导致 RubyScriptEngine 类加载失败,这个失败原因被吃掉了,和 ruby 对应不起来,当用户执行 ruby 脚本时,会报不支持 ruby,而不是真正失败的原因。
  • 增加了对扩展点 IOC 和 AOP 的支持,一个扩展点可以直接 setter 注入其它扩展点。

在以上改进项中,第一个改进项比较好理解。第二个改进项没有进行验证,就不多说了。第三个改进项是增加了对 IOC 和 AOP 的支持,这是什么意思呢?这里简单解释一下,Dubbo SPI 加载完拓展实例后,会通过该实例的 setter 方法解析出实例依赖项的名称。比如通过 setProtocol 方法名,可知道目标实例依赖 Protocal。知道了具体的依赖,接下来即可到 IOC 容器中寻找或生成一个依赖对象,并通过 setter 方法将依赖注入到目标实例中。说完 Dubbo IOC,接下来说说 Dubbo AOP。Dubbo AOP 是指使用 Wrapper 类(可自定义实现)对拓展对象进行包装,Wrapper 类中包含了一些自定义逻辑,这些逻辑可在目标方法前行前后被执行,类似 AOP。Dubbo AOP 实现的很简单,其实就是个代理模式。这个官方文档中有所说明,大家有兴趣可以查阅一下。

关于 Dubbo SPI 的演示,以及与 Java SPI 的对比就先这么多,接下来加入源码分析阶段。

相关文章:

Dubbo 源码分析 – SPI 机制

1.简介 SPI 全称为 Service Provider Interface&#xff0c;是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中&#xff0c;并由服务加载器读取配置文件&#xff0c;加载实现类。这样可以在运行时&#xff0c;动态为接口 加载实现类。正因此特性&#xff0…...

JDBC概述二(JDBC编程+案例展示)

一&#xff08;JDBC的编程步骤&#xff09; 1.加载数据库驱动 加载数据库驱动通常使用class类的静态方法forName&#xff08;&#xff09;来实现&#xff0c;具体实现方式如下&#xff1a; Class.forName&#xff08;“DriverName”&#xff09;&#xff0c;DriverName就是数…...

广度和深度优先搜索解析与示例代码

一,什么是搜索算法 算法是基于特定数据结构之上的,深度优先搜索算法和广度优先搜索算法都是基于“图”这种数据结构的。 树是图的一种特例(连通无环的图就是树)。 图上的搜索算法,最直接的理解就是,在图中找出从一个顶点出发,到另一个顶点的路径。具体方法有很多,两种…...

基于SLIC超像素的归一化分割算法

论文&#xff1a;基于SLIC超像素的归一化分割方法研究 归一化分割的缺点&#xff1a;单独使用时无法区分很接近的图像区域&#xff0c;实时性也差。 区域接近问题&#xff1a;描述图像间相互关系的权重函数的取值&#xff0c;体现图像间的信息特征&#xff0c;影响分割效果。…...

C语言刷题(4)——“C”

各位CSDN的uu们你们好呀&#xff0c;今天小雅兰的内容又到了我们的复习啦&#xff0c;那么还是刷题噢&#xff0c;话不多说&#xff0c;让我们进入C语言的世界吧 BC55 简单计算器 BC56 线段图案 BC57 正方形图案 BC58 直角三角形图案 BC59 翻转直角三角形图案 BC60 带空格…...

带你看懂RuoYi动态数据源切换

文章目录数据源是什么一、spring中是如何处理各种数据源的&#xff1f;1.开搞springboot2.创建一个测试类二、有了如上的理论,那么想想动态切换数据源吧参考若依的动态数据源配置总结数据源是什么 数据源,对于java来说,就是可用的数据库,那么我平时开发的springboot springclo…...

家有女儿必看:盲目的和青春期女儿较劲,不如掌握4个沟通技巧

导读&#xff1a;家有女儿必看&#xff1a;盲目的和青春期女儿较劲&#xff0c;不如掌握4个沟通技巧 各位点开这篇文章的朋友们&#xff0c;想必都是很高的颜值吧&#xff0c;我们真的是很有缘哦&#xff0c;小编每天都会给大家带来不一样的育儿资讯&#xff0c;如果对小编的文…...

【VC 7/8】vCenter Server 基于文件的备份和还原Ⅰ——基于文件的备份和还原的注意事项和限制

目录1.1 协议1.2 还原后配置说明1.3 Storage DRS1.4 分布式电源管理1.5 分布式虚拟交换机1.6 内容库1.7 虚拟机生命周期操作1.8 vSphere High Availability1.9 基于存储策略的管理1.10 其它注意事项虚拟存储区域网络修补关联博文[图片来源]&#xff1a;https://www.vmignite.co…...

【ROS学习笔记10】ROS中配置自定义Cpp头文件和导入自定义Python库

【ROS学习笔记10】ROS中配置自定义Cpp头文件和导入自定义Python库 文章目录【ROS学习笔记10】ROS中配置自定义Cpp头文件和导入自定义Python库一、ROS中的头文件和源文件1.1 自定义头文件调用1.2 自定义源文件调用二、Python模块的导入Reference写在前面&#xff0c;本系列笔记参…...

svn 分支(branch)和标签(tag)管理

版本控制的一大功能是可以隔离变化在某个开发线上&#xff0c;这个开发线就是分支&#xff08;branch&#xff09;。分支通常用于开发新功能&#xff0c;而不会影响主干的开发。也就是说分支上的代码的编译错误、bug不会对主干&#xff08;trunk&#xff09;产生影响。然后等分…...

@Transactional详解

一、事务的概念 百度百科&#xff1a; 事务&#xff08;Transaction&#xff09;&#xff0c;一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执 行单元(unit)。事务通常由高级数据库操纵语言或编程语言&#xff08;如SQL&#x…...

机器学习:Transformer

Transformer sequence-to-sequence(seq2seq) 很大语音没有文本&#xff0c;7000种中超半数没有文字。 遇到的问题&#xff1a; 遇到问题时候可以先不管它&#xff0c;先出一个baseline看看效果&#xff0c;后续再进行提升。 tts&#xff1a; 文本转语音&#xff0c;语音合成…...

pytorch-模型构建,参数访问,模型存取API接口,对比学习

多层感知机的简洁实现pytorch-多层感知机&#xff0c;最简单的深度学习模型&#xff0c;将非线性激活函数引入到模型中。_羞儿的博客-CSDN博客中含单隐藏层的多层感知机的实现方法。首先构造Sequential实例&#xff0c;然后依次添加两个全连接层。其中第一层的输出大小为256&am…...

javaEE 初阶 — 数据链路层中的以太网数据帧

文章目录以太网帧格式1. MAC 地址2. MAC 地址是如何与 IP 地址相互配合的3. 以太网帧格式中的类型MTU&#xff08;了解&#xff09;以太网帧格式 数据链路层主要考虑的是相邻的两个结点之间的传输。 这里最知名的协议就是 以太网。 一个以太网数据帧有三个部分组成。帧头载荷…...

泼辣修图Polarr5.11.4 版,让你的创意无限延伸

泼辣修图是一款非常实用的图片处理软件&#xff0c;它不仅拥有丰富的图片处理功能&#xff0c;而且还能够轻松地实现自定义操作。泼辣修图的操作界面非常简洁&#xff0c;功能也非常丰富&#xff0c;使用起来非常方便快捷。 泼辣修图拥有非常丰富的图片处理功能&#xff0c;包括…...

leetcode打卡-深度优先遍历和广度优先遍历

200.岛屿数量 leetcode题目链接&#xff1a;https://leetcode.cn/problems/number-of-islands leetcode AC记录&#xff1a; 思路&#xff1a;深度优先遍历&#xff0c;从0&#xff0c;0开始遍历数组&#xff0c;使用boolean类型数组used记录是否被访问过&#xff0c;进行一…...

【0177】Linux中POSIX信号量实现机制

文章目录 1. 信号量概念1.1 信号量类比1.2 重要的观察1.3 信号量分类2. POSIX与System V信号量3. 信号量API4. 代码演示5. 信号量内核实现1. 信号量概念 在计算机科学中,信号量(semaphores )是一种变量或抽象数据类型,用于控制多个进程对公共资源的访问,并避免并发系统(如…...

跳表--C++实现

目录 作者有话说 为何要学习跳表&#xff1f;为了快&#xff0c;为了更快&#xff0c;为了折磨自己..... 跳表作用场景 1.不少公司自己会设计哈希表&#xff0c;如果解决哈希冲突是不可避免的事情。通常情况下会使用链址&#xff0c;很好理解&#xff0c;当有冲突产生时&#…...

c#:System.Text.Json 的使用一

环境&#xff1a; .net 6.0vs2022 参考&#xff1a; 从 Newtonsoft.Json 迁移到 System.Text.Json System.Text.Json 常规用法 一、写入时的控制 1.1 非ascii码转换 直接看代码&#xff1a; var str System.Text.Json.JsonSerializer.Serialize(new Model { Id 1, Name …...

kaggle数据集下载当中所遇到的问题

kaggle数据集下载当中所遇到的问题报错分析pip install kagglethe SSL module is not available解决方法pip的版本升级解决办法下载kaggle包kaggle数据集下载问题解决参考内容报错分析 今天在尝试使用pip install kaggle的方法去下载我需要的数据集的时候遇到了一些报错的问题…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...

如何做好一份技术文档?从规划到实践的完整指南

如何做好一份技术文档&#xff1f;从规划到实践的完整指南 &#x1f31f; 嗨&#xff0c;我是IRpickstars&#xff01; &#x1f30c; 总有一行代码&#xff0c;能点亮万千星辰。 &#x1f50d; 在技术的宇宙中&#xff0c;我愿做永不停歇的探索者。 ✨ 用代码丈量世界&…...