一、定义

Dubbo 的 SPI (Service Provider Interface) 机制是对 Java 原生 SPI 机制的增强和扩展,提供了更强大的扩展能力

二、Dubbo SPI 核心实现原理

1、配置文件结构

Dubbo SPI 的配置文件位于:META-INF/dubbo/ 或 META-INF/dubbo/internal/ 或 META-INF/services/

文件名为接口的全限定名,内容为键值对格式:

2、核心类分析

ExtensionLoader,Dubbo SPI 的核心入口类,主要功能:

  • 加载并解析扩展点配置

  • 缓存已加载的扩展点

  • 创建扩展点实例

  • 处理扩展点依赖注入

重要方法:

  • getExtension(String name):获取指定名称的扩展实现

  • getAdaptiveExtension():获取自适应扩展

  • getActivateExtension(URL url, String[] values):获取激活的扩展

扩展点加载流程

1、通过 ExtensionLoader.getExtensionLoader(Class type) 获取扩展点加载器

2、加载器读取配置文件,解析扩展点实现类

3、根据名称实例化具体的扩展点实现

4、注入扩展点的依赖

5、如果存在Wrapper类,进行包装

6、返回最终的扩展点实例

三、Dubbo SPI 高级特性

1、自适应扩展机制 (@Adaptive)

Dubbo 的自适应扩展机制允许在运行时动态选择具体的扩展实现。

实现方式:

Dubbo 会为带有 @Adaptive 注解的方法生成适配代码,根据URL参数动态选择实现

2、自动包装机制 (Wrapper)

Dubbo 支持自动包装扩展点实现,类似AOP的概念。当扩展点实现类的构造函数包含扩展点接口类型参数时,Dubbo会自动将其识别为Wrapper类

示例:

3、自动激活机制 (@Activate)

用于根据条件自动激活一组扩展实现,常用于过滤器、拦截器等场景

可以通过URL参数指定激活哪些扩展:dubbo://service?filter=trace,monitor

四、Dubbo SPI 代码示例

1、定义SPI接口

首先,我们需要定义一个SPI接口。假设我们要创建一个日志记录器接口:

  package com.example.spi;

  public interface Logger {
void log(String message);
}

2、提供接口的实现类

接下来,我们提供该接口的两个实现类:ConsoleLogger.java、FileLogger.java

package com.example.spi.impl;
import com.example.spi.Logger; public class ConsoleLogger implements Logger {
@Override
public void log(String message) {
System.out.println("ConsoleLogger: " + message);
}
} public class FileLogger implements Logger {
@Override
public void log(String message) {
// 这里只是模拟文件日志记录,实际中应写入文件
System.out.println("FileLogger: " + message);
}
}

3、配置文件

在META-INF/dubbo/com.example.spi.Logger文件中指定实现类的全限定名:

console=com.example.spi.impl.ConsoleLogger
file=com.example.spi.impl.FileLogger

4、使用ExtensionLoader加载实现类

最后,我们使用Dubbo的ExtensionLoader来加载并使用这些实现类:

  package com.example.spi;
import org.apache.dubbo.common.extension.ExtensionLoader; public class SPITest {
public static void main(String[] args) {
// 加载Logger接口的扩展点
ExtensionLoader<logger> loader = ExtensionLoader.getExtensionLoader(Logger.class); // 获取ConsoleLogger实现类实例
Logger consoleLogger = loader.getExtension("console");
consoleLogger.log("This is a console log message."); // 获取FileLogger实现类实例
Logger fileLogger = loader.getExtension("file");
fileLogger.log("This is a file log message.");
}
}

5、运行上述代码,输出结果如下:

ConsoleLogger: This is a console log message.
FileLogger: This is a file log message.

五、Dubbo SPI 源码分析

1、扩展点加载过程

ExtensionLoader 加载扩展点的关键流程:

  • getExtensionLoader():获取或创建指定类型的ExtensionLoader

  • loadExtensionClasses():加载并解析扩展点配置

  • createExtension():创建扩展点实例

    • 通过反射实例化类

    • 执行依赖注入(injectExtension)

    • 应用Wrapper包装

  • 缓存已创建的扩展点实例

2、依赖注入实现

Dubbo 通过 injectExtension() 方法实现依赖注入:

3、自适应扩展代码生成

Dubbo 会为 @Adaptive 方法动态生成适配类,例如:

详细介绍Dubbo的SPI机制的更多相关文章

  1. 面试常问的dubbo的spi机制到底是什么?

    前言 dubbo是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力.作为spring cloud alibaba体系中重要的一部分,随着spring cloud alibaba在 ...

  2. 某大厂面试题:说一说Java、Spring、Dubbo三者SPI机制的原理和区别

    大家好,我是三友~~ 今天来跟大家聊一聊Java.Spring.Dubbo三者SPI机制的原理和区别. 其实我之前写过一篇类似的文章,但是这篇文章主要是剖析dubbo的SPI机制的源码,中间只是简单地 ...

  3. dubbo的spi机制

    SPI SPI是一种扩展机制,在java中SPI机制被广泛应用,比如Spring中的SpringServletContainerInitializer 使得容器启动的时候SpringServletCo ...

  4. Dubbo的SPI机制与JDK机制的不同及原理分析

    从今天开始,将会逐步介绍关于DUbbo的有关知识.首先先简单介绍一下DUbbo的整体概述. 概述 Dubbo是SOA(面向服务架构)服务治理方案的核心框架.用于分布式调用,其重点在于分布式的治理. 简 ...

  5. jdk和dubbo的SPI机制

    前言:开闭原则一直是软件开发领域中所追求的,开闭原则中的"开"是指对于组件功能的扩展是开放的,是允许对其进行功能扩展的,“闭”,是指对于原有代码的修改是封闭的,即不应该修改原有的代 ...

  6. Dubbo剖析-SPI机制

    文章要点: 1.什么是SPi 2.Dubbo为什么要实现自己的SPi 3.Dubbo的IOC和AOP 4.Dubbo的Adaptive机制 5.Dubbo动态编译机制 6.Dubbo与Spring的融 ...

  7. 详细介绍Java垃圾回收机制

    垃圾收集GC(Garbage Collection)是Java语言的核心技术之一,之前我们曾专门探讨过Java 7新增的垃圾回收器G1的新特性,但在JVM的内部运行机制上看,Java的垃圾回收原理与机 ...

  8. dubbo源码分析1——SPI机制的概要介绍

    插件机制是Dubbo用于可插拔地扩展底层的一些实现而定制的一套机制,比如dubbo底层的RPC协议.注册中心的注册方式等等.具体的实现方式是参照了JDK的SPI思想,由于JDK的SPI的机制比较简单, ...

  9. 详解Apache Dubbo的SPI实现机制

    一.SPI SPI全称为Service Provider Interface,对应中文为服务发现机制.SPI类似一种可插拔机制,首先需要定义一个接口或一个约定,然后不同的场景可以对其进行实现,调用方在 ...

  10. Dubbo中SPI扩展机制解析

    dubbo的SPI机制类似与Java的SPI,Java的SPI会一次性的实例化所有扩展点的实现,有点显得浪费资源. dubbo的扩展机制可以方便的获取某一个想要的扩展实现,每个实现都有自己的name, ...

随机推荐

  1. css笔记详解

    css讲解  首先在我们学习css之前先来思考一个问题,为什么html标签上不直接改变样式,而要将文档结构和样式分离,分别用html和css来表示呢? 其实我个人认为这样分离带来的好处明显,我总结了几 ...

  2. DICOM-SCP,可以直接使用的SCP(.net framework 4.5)控制台接收端

    此程序引用的是Dicom.Core 4.0.8.0,也是最后一版支持部署在.net framework 4.5 或以下环境的.如需要部署在.net4.6.1以上的需要查看另一个文档. 1 using ...

  3. Nickel pg walkthrough Intermediate window

    nmap ┌──(root㉿kali)-[~] └─# nmap -p- -A -sS 192.168.196.99 Starting Nmap 7.94SVN ( https://nmap.org ...

  4. 自定义swagger扩展解析jsondoc

    需求规定 为了减少注释和swagger注解的重复定义, 通过规范注释, 让swagger可以通过javadoc来产生 替换@Api.@ApiOperation.@ApiModel.@ApiModelP ...

  5. HT-018 Div3 构造 题解 [ 黄 ] [ 数学 ] [ 结论 ]

    构造:结论题,gcy数竞大佬tql%%%orz. 结论 先放结论:如果 \(x \bmod 4=2\) ,那么 \(x\) 无法被表示为 \(a^2-b^2\) 的形式:除此之外的其他数都可以. 证明 ...

  6. deepseek等AI工具是程序员技能发展的双刃剑

    2025年,全球已有73%的程序员日常使用AI编码工具(Gartner 2025Q1数据).当我们惊叹于GitHub Copilot生成完整功能模块仅需10秒时,也需要警惕一个现象:新一代程序员在ID ...

  7. 最新demo版 | 如何0-1开发支付宝小程序之小程序页面功能介绍(三)

    前两期讲了小程序开发的准备工作以及前期需要如何调试,今天我们就来介绍下开发一个支付宝小程序页面需要了解哪些信息. 一个小程序页面的整体功能的构成离不开页面展示(AXML).页面样式(ACSS)以及页面 ...

  8. 运用myabits

    要使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可. 如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中: ...

  9. AD22 solder层开窗不见了什么原因?PCB阻焊层不显示阻焊。

    做回来的板子焊盘没有开窗! 3D上看也是没有的! 上网查了,在设计->规则->Mask->SolderMaskExpansion 将盖油勾选去掉即可. END

  10. Shell - 脚本案例

    题记部分 一.节点状态监控脚本(nodeStatusCheck.sh) [脚本名称]nodeStatusCheck.sh [监控规则]通过ping的方式监控集群节点状态,检查节点是否失联 [实现方式] ...