Dubbo 与 Spring 整合全流程解析(含生产者与消费者
角色核心 Bean主要职责Provider暴露服务、注册服务Consumer引用服务、订阅服务列表、生成代理Registry保存动态服务列表Protocol创建服务端/客户端通讯生成服务接口代理ClusterFailoverCluster 等集群容错Spring XML——> 最终返回代理对象。
Dubbo 与 Spring 整合全流程解析(含生产者与消费者)
本文从一次 Dubbo 服务调用的执行路径出发,完整梳理 Dubbo 与 Spring 的整合机制,包括:
- Spring 如何加载 Dubbo 配置
- 生产者如何暴露服务
- 消费者如何引用服务
- 消费者如何拿到远程元数据并发起调用
- ServiceBean、ReferenceBean、Proxy、Cluster、Invoker 等核心类的作用
适用于理解 Dubbo 2.5~2.7 经典版本的整体架构与源码入口。
一、Spring 与 Dubbo 的整合方式概览
在 XML 配置模式下,例如:
<dubbo:application name="demo-consumer" />
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:reference id="demoService" interface="com.xxx.DemoService" />
Spring 会通过 Dubbo 提供的 NamespaceHandler 扩展能力来解析 <dubbo:xxx> 标签。
核心扩展类:
DubboNamespaceHandler:负责注册各种标签解析器DubboBeanDefinitionParser:将 dubbo:service、dubbo:reference、dubbo:registry 等标签解析成 Spring Bean
最终这些 Bean 会在 Spring 容器启动时转换为:
- Provider 侧:
ServiceBean - Consumer 侧:
ReferenceBean
这两个 Bean 是 Dubbo 与 Spring 集成的核心。
二、生产者(Provider)启动流程
2.1 Spring 解析 <dubbo:service> 标签
<dubbo:service interface="com.xxx.DemoService" ref="demoServiceImpl" />
Spring 会解析成一个 ServiceBean。
ServiceBean 继承了:
ApplicationListenerInitializingBeanFactoryBeanDisposableBean
因此它可以:
- 在 Spring 启动后自动暴露服务
- 在容器关闭时注销服务
2.2 Spring 完成初始化后触发 onApplicationEvent
ServiceBean 在 onApplicationEvent(ContextRefreshedEvent event) 中会调用:
serviceBean.export()
export 的主要行为:
-
生成
Invoker(由ProxyFactory创建) -
通过
Protocol暴露服务,例如:- DubboProtocol
- InjvmProtocol
-
根据 Registry 配置,将服务信息注册到注册中心
最终生产者会:
- 本地开启 Netty Server(DubboProtocol)
- 注册 URL 到注册中心(例如 zookeeper)
三、消费者(Consumer)启动流程
3.1 Spring 解析 <dubbo:reference> 标签
例如:
<dubbo:reference id="demoService" interface="com.xxx.DemoService" />
Spring 会解析为一个 ReferenceBean。
ReferenceBean 同样实现了 FactoryBean,因此在 getObject() 时会创建真正的代理对象。
3.2 ReferenceBean 初始化 → 向注册中心订阅服务
ReferenceBean.getObject() 中会执行:
ref = createProxy(map)
createProxy 内部会:
- 通过
RegistryDirectory向注册中心订阅 Provider 列表 - 将注册中心返回的 URL 转换为 Invoker 列表
- 通过 Cluster 进行集群容错包装,例如:FailoverCluster
- 使用 ProxyFactory 生成最终的 Consumer 调用代理
因此,当消费者获取 demoService 时:
DemoService demoService = context.getBean("demoService");
实际返回的不是 demoServiceImpl,而是一个代理类(Javassist/ByteBuddy 动态生成)。
四、消费者如何拿到元数据并构造 Invoker?
执行顺序如下:
4.1 RegistryDirectory 向注册中心订阅
ReferenceBean 创建 Directory(例如:RegistryDirectory)。
Directory 会根据 interfaceName 在注册中心发起订阅:
consumer subscribes to provider URLs
注册中心推送的数据包括:
- providers
- routers
- configurators
4.2 将 Provider URL 转换为 Invoker
RegistryDirectory 会根据 protocol 的不同生成 Invoker:
DubboProtocol.refer()
refer 内部会:
- 创建一个 DubboInvoker
- 建立连接或懒加载连接
4.3 集群包装 Invoker
多个 Provider → 多个 Invoker
Cluster.merge() 之后:
- FailoverClusterInvoker
- FailfastClusterInvoker
- ForkingClusterInvoker
最终只暴露 一个 ClusterInvoker 给上层代理。
五、方法调用过程:从代理到网络传输
当你写:
demoService.sayHello("world")
流程如下:
- 代理类(Proxy)将方法封装成 RpcInvocation
- 调用 ClusterInvoker.invoke()
- ClusterInvoker 调用具体的 DubboInvoker.invoke()
- DubboInvoker 通过 ExchangeClient 发送请求
- NettyClient 发送数据到 Provider
- Provider 在 NettyServer 上收到请求
- 转到 DubboProtocol 分发请求
- 调用真正的 DemoServiceImpl 实现
- 结果通过 Netty 回传
整个过程无感知、透明。
六、总结:Dubbo & Spring 的整合核心思想
| 角色 | 核心 Bean | 主要职责 |
|---|---|---|
| Provider | ServiceBean | 暴露服务、注册服务 |
| Consumer | ReferenceBean | 引用服务、订阅服务列表、生成代理 |
| Registry | RegistryDirectory | 保存动态服务列表 |
| Protocol | DubboProtocol | 创建服务端/客户端通讯 |
| ProxyFactory | JavassistProxyFactory | 生成服务接口代理 |
| Cluster | FailoverCluster 等 | 集群容错 |
整体流程图:
Spring XML
dubbo:service ——> ServiceBean ——> export()
——> Protocol ——> NettyServer
——> Registry
dubbo:reference ——> ReferenceBean ——> getObject()
——> RegistryDirectory.subscribe
——> Protocol.refer()
——> Cluster.merge()
——> ProxyFactory
——> 最终返回代理对象
更多推荐



所有评论(0)