news 2026/6/24 7:41:55

Dubbo 源码里搓了4种设计模式,比 Spring 还直白

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Dubbo 源码里搓了4种设计模式,比 Spring 还直白

看 Spring 源码里的设计模式,很多时候你得绕好几层才能看到模式的全貌。Dubbo 不一样,它用模式用得很"明目张胆"——连类名都告诉你了。

ProtocolProxyFactoryClusterLoadBalance……这些接口和实现之间的关系,就是设计模式教科书级别的案例。今天拆 4 个最典型的。

1. SPI + 工厂方法:扩展点加载机制

Dubbo 最核心的设计不是某个设计模式,而是它自己的 SPI 扩展机制。但这个机制的底层就是工厂方法模式。

java // ExtensionLoader 本质是一个工厂 public class ExtensionLoader<T> { // 根据名字创建扩展实例 — 典型工厂方法 public T getExtension(String name) { Holder<Object> holder = getOrCreateHolder(name); Object instance = holder.get(); if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { instance = createExtension(name); // 创建具体实例 holder.set(instance); } } } return (T) instance; } }

调用方式:

java Protocol protocol = ExtensionLoader .getExtensionLoader(Protocol.class) .getExtension("dubbo"); // 按名字加载具体实现

ExtensionLoader是工厂,Protocol是产品接口,DubboProtocolHttpProtocolRedisProtocol是具体产品。你不需要new任何实现类,只要在META-INF/dubbo下配置好扩展点,工厂帮你创建。

这比 Spring 的BeanFactory更直白:你不需要注解、不需要容器启动,一行代码拿到扩展实例。

2. 装饰器模式:Protocol 的包装链

Dubbo 里的Protocol接口有一堆实现,有些是真正的协议,有些是装饰器。看源码:

```java // 真正的协议实现 public class DubboProtocol implements Protocol { ... } public class HttpProtocol implements Protocol { ... }

// 装饰器:给 Protocol 加功能 public class ProtocolFilterWrapper implements Protocol { private Protocol protocol; // 持有被装饰对象

public <T> Exporter<T> export(Invoker<T> invoker) { // 先构建 Filter 链,再委托给真正的 Protocol return protocol.export(buildInvokerChain(invoker, ...)); }

}

public class ProtocolListenerWrapper implements Protocol { private Protocol protocol;

public <T> Exporter<T> export(Invoker<T> invoker) { // 加监听器逻辑,再委托 return protocol.export(invoker); }

}

public class QosProtocolWrapper implements Protocol { private Protocol protocol; // 加 QoS 功能 } ```

加载顺序:先加载真正的 Protocol,然后用装饰器一层层包上去:

QosProtocolWrapper └─ ProtocolListenerWrapper └─ ProtocolFilterWrapper └─ DubboProtocol ← 真正干活的

这就是装饰器模式的精髓:不修改原始类,通过包装给它加功能。而且装饰器可以无限叠加,每层只管自己的事。

Dubbo 的 Filter 链也是装饰器模式的变体。你在配置文件里加的timeoutmonitorexceptionFilter,都是一个个装饰器,把Invoker包装后返回。

3. 策略模式:负载均衡

这是 Dubbo 里最容易看懂的策略模式——连接口名都叫LoadBalance

java @SPI(RandomLoadBalance.NAME) public interface LoadBalance { <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation); }

四种策略实现:

java public class RandomLoadBalance extends AbstractLoadBalance { ... } // 随机 public class RoundRobinLoadBalance extends AbstractLoadBalance { ... } // 轮询 public class LeastActiveLoadBalance extends AbstractLoadBalance { ... } // 最少活跃 public class ConsistentHashLoadBalance extends AbstractLoadBalance { ... } // 一致性哈希

选择哪个策略?配置决定:

xml <dubbo:reference loadbalance="roundrobin" />

运行时通过 SPI 加载对应实现:

java LoadBalance lb = ExtensionLoader .getExtensionLoader(LoadBalance.class) .getExtension("roundrobin");

不写 if-else,不写 switch,策略的切换完全由配置驱动。新增负载均衡算法?写个实现类 + 配置文件就行,零侵入。

4. 模板方法模式:AbstractProtocol

Dubbo 的Protocol接口有两个核心方法:export(暴露服务)和refer(引用服务)。不同协议的实现逻辑差异很大,但有些公共步骤是固定的。

AbstractProtocol把这些公共步骤抽到模板方法里:

```java public abstract class AbstractProtocol implements Protocol {

// 模板方法:暴露服务的公共骨架 public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { // 公共逻辑:校验 URL、记录 exporter 等 URL url = invoker.getUrl(); String key = serviceKey(url); Exporter<T> exporter = doExport(invoker, url, key); // 子类实现 exporterMap.put(key, exporter); return exporter; } // 子类必须实现的抽象方法 protected abstract <T> Exporter<T> doExport(Invoker<T> invoker, URL url, String key); // 引用服务同理 public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException { // 公共逻辑 Invoker<T> invoker = doRefer(type, url); // 子类实现 return invoker; } protected abstract <T> Invoker<T> doRefer(Class<T> type, URL url);

} ```

DubboProtocol只需要关心自己的doExportdoRefer

java public class DubboProtocol extends AbstractProtocol { @Override protected <T> Exporter<T> doExport(Invoker<T> invoker, URL url, String key) { // 打开 Server、注册到注册中心 等 Dubbo 特有逻辑 openServer(url); optimizeSerialization(url); return new DubboExporter<>(invoker, key, exporterMap); } }

公共逻辑不重复,协议特有逻辑各写各的。如果以后新增一个 gRPC 协议,继承AbstractProtocol实现两个方法就行。

跟 Spring 对比着看

| 模式 | Spring 怎么用 | Dubbo 怎么用 | |------|-------------|------------| | 工厂方法 | BeanFactory + 各种 FactoryBean | ExtensionLoader 直接按名加载 | | 装饰器 | BeanWrapper、各种 Proxy | ProtocolFilterWrapper 等包装链 | | 策略 | Resource 接口不同实现 | LoadBalance 接口不同实现 | | 模板方法 | AbstractApplicationContext | AbstractProtocol |

Dubbo 的特点是用得更"裸":没有 IoC 容器帮你管理生命周期,模式就是模式,代码里一目了然。看 Spring 源码你得先搞懂容器机制才能看到模式,看 Dubbo 源码模式直接摊开在你面前。

对初学者来说,Dubbo 源码是比 Spring 更好的设计模式学习材料——不是因为它更高级,而是因为它更直白。

我在做的小程序「爪爪代码冒险记」也在尝试用更直白的方式讲设计模式,漫画+答题的形式,比啃源码轻松一点,感兴趣可以搜搜。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 17:42:09

MSC8101嵌入式系统硬件设计:从电源、时钟到总线调试的实战指南

1. 项目概述与核心挑战在通信和工业控制领域&#xff0c;基于飞思卡尔&#xff08;Freescale&#xff0c;现为NXP&#xff09;MSC8101这类高性能数字信号处理器的嵌入式系统设计&#xff0c;一直是个既考验硬件功底又充满细节挑战的活儿。这颗芯片集成了强大的SC140 DSP核心和丰…

作者头像 李华
网站建设 2026/6/8 17:20:31

从S12ZVM到S32M2xx:电机控制MCU的架构、外设与迁移实战解析

1. 项目概述&#xff1a;从S12ZVM到S32M2xx&#xff0c;一次面向未来的电机控制MCU升级解析在汽车电子&#xff0c;尤其是电机控制领域干了十几年&#xff0c;我经手过不少项目&#xff0c;从早期的8位机到现在的32位Arm内核&#xff0c;深刻体会到微控制器&#xff08;MCU&…

作者头像 李华
网站建设 2026/6/9 17:41:03

[操作系统]虚拟机技术

虚拟机分类&#xff1a;第一类虚拟机&#xff08;裸金属型&#xff09;和第二类虚拟机&#xff08;托管型&#xff09;。用过的的虚拟机&#xff1a;服务器的虚拟化用第一类虚拟机&#xff0c;QingCloud/天鸿云虚拟平台。Windows Server和Linux Server。桌面版的虚拟化/Windows…

作者头像 李华
网站建设 2026/6/9 18:32:01

AI 驱动的个人知识库:自动整理笔记与智能问答实战

很多开发者都有这样的痛点&#xff1a;收藏了成千上万篇技术文章、PDF 文档和代码片段&#xff0c;散落在硬盘的各个角落。当真正需要某个具体解决方案时&#xff0c;往往要在几十个文件夹里翻找半天&#xff0c;甚至因为记不清关键词而彻底放弃。传统的全文搜索工具虽然能匹配…

作者头像 李华
网站建设 2026/6/8 17:11:43

Windows 10 OneDrive残留问题的自动化清理方案实现

Windows 10 OneDrive残留问题的自动化清理方案实现 【免费下载链接】OneDrive-Uninstaller Batch script to completely uninstall OneDrive in Windows 10 项目地址: https://gitcode.com/gh_mirrors/on/OneDrive-Uninstaller Windows 10系统中OneDrive的深度集成设计导…

作者头像 李华