Dubbo源码解析(三)
一、Dubbo整合Spring启动流程
Dubbo的使用可以不依赖Spring,但是生产环境中Dubbo都是整合到Spring中一起使用,所以本章就解析Dubbo整合Spring的启动流程
一、传统的xml解析方式
一、Dubbo配置解析流程
在Java 中,一切皆对象。在JDK 中使用java.lang.Class 来描述类这个对象。而在Spring 中,bean 对象是操作核心。那么Spring 也需要一个东西来描述bean 这个对象,它就是BeanDefinition。
dubbo 的配置解析,不论是xml 方式的配置,还是注解的配置,目标都是把配置的属性值提取出来,变成dubbo 的组件bean(先由BeanDefinition 描述,然后委托spring 生成组件bean)。
下面以xml 的标签为例,列出每种配置对应要解析成为的目标组件bean。

首先,dubbo 自定义了spring 标签描述dubbo.xsd。在dubbo-config-spring模块下的src/main/resouce/META-INF 下,其次,在spring.handlers、spring.schemas 中指定解析类,将标签引入spring 中管理。


来到DubboNamespaceHandler中的init()方法,引入了很多DubboBeanDefinitionParser类,每个类会解析对应的配置,DubboBeanDefinitionParser 继承了spring 的BeanDefinitionParser 接口,spring 会调用parse 方法来读取每个标签配置,将属性值装入对应的BeanDefinition 定义中,后续spring会根据此BeanDefinition 定义生成dubbo 的组件bean。

继续看下DubboNamespaceHandler中的parse()方法,spring启动过程中同样会调用到这个方法,方法中有一行DubboSpringInitializer.initialize(parserContext.getRegistry())方法,就是向容器中加入一些基础bean。

我们先看两个比较重要的也就是ReferenceAnnotationBeanPostProcessor,DubboDeployApplicationListener;其中ReferenceAnnotationBeanPostProcessor是处理@Reference注解的,而DubboDeployApplicationListener是DubboDeployApplicationListener会监听Spring容器启动完成事件ContextRefreshedEvent,一旦接收到这个事件后,就会开始Dubbo的启动流程,就会执行DefaultModuleDeployer的start()进行服务导出与服务引入。
![]()


到此,那么dubbo中的一些必要的基本类已经假如到容器中了,也就是已经具备了解析处理dubbo.xml的基本条件。
二、Service标签处理
看下解析service标签的DubboBeanDefinitionParser,spring启动过程中会执行到parse方法,最终将service对应的Class信息设置到beanDefinition中,并且调用registerBeanDefinition方法将该beanDefinition注册到BeanDefinition中。




注意到此时的beanClass为ServiceBean,该类实现了InitializingBean接口,那么最终实例化的时候会调用afterPropertiesSet方法,这里会将ServiceBean加入到dubbo的configsCache缓存中,后面进行服务暴漏的时候就是从这个缓存中获取的。


三、Reference标签处理

![]()
同理reference标签的处理跟service标签一样,同样会通过DubboBeanDefinitionParser将他的class信息设置到beanDefinition中,此时class信息为referenceBean。这个接口实现了FactoryBean接口,那么最终spring会调用他的getObject方法,可以看到该方法里面去创建代理对象lazyProxy对象。



referenceBean同时也实现了InitializingBean,最终也会调用到afterPropertiesSet()方法,这里会将referenceBean添加到缓存中。


四、DubboDeployApplicationListener
当Spring容器启动完成会发布事件ContextRefreshedEvent,DubboDeployApplicationListener会监听这个事件,一旦接收到这个事件后,就会开始Dubbo的启动流程,就会执行DefaultModuleDeployer的start()进行服务导出(服务暴漏)与服务引用。
![]()


还记得serviceBean初始化的时候执行的afterPropertiesSet方法吗,会将ServiceBean加入到dubbo的configsCache缓存中,这里会取出来挨个进行服务导出。

同时也会从configManager中获取references进行服务的引用,也就是生成具体的远程调用代理类,最终会调用到referenceConfig中的init方法,ref就是生成的代理对象,也就是实际的业务执行者。




![]()
二、注解方式
一、@EnableDubbo
服务端代码如下:需要在配置类上加上@EnableDubbo注解

@EnableDubbo注解上面有一个注解@DubboComponentScan,点进去这个注解发现他引入了这个DubboComponentScanRegistrar,该类实现了ImportBeanDefinitionRegistrar,spring启动过成功会调用registerBeanDefinitions方法


这里有三个比较关键的方法:

1、DubboSpringInitializer.initialize(registry);
这一步在xml解析的过程中已经解释过,引入了ReferenceAnnotationBeanPostProcessor,DubboDeployApplicationListener两个核心类;
2、Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
这一步是获取@DubboComponentScan上面的包路径,并传递给ServiceAnnotationPostProcessor,这个类会去扫描这个包下的带有@DubboService注解的类
3、将ServiceAnnotationPostProcessor注入到spring容器中,后续进行@DubboService注解解析![]()
二、ServiceAnnotationPostProcessor
这个类实现了BeanDefinitionRegistryPostProcessor,最终Spring会调用到postProcessBeanDefinitionRegistry方法中,而scanServiceBeans方法就是将包路径下带有@DubboService的类解析为beanDefinition然后加入到spring容器中。



最终还是会通过serviceBean的afterPropertiesSet方法将ServiceBean加入到dubbo的configsCache缓存中,后面进行服务暴漏的时候就是从这个缓存中获取的
三、ReferenceAnnotationBeanPostProcessor


spring执行过程中会调用postProcessMergedBeanDefinition方法收集类中带有@DubboReference注解的属性,并最终调用postProcessPropertyValues将类上的属性注入到类中。

referenceBean也实现了InitializingBean,最终也会调用到afterPropertiesSet()方法,这里会将
referenceBean添加到缓存中。


四、DubboDeployApplicationListener
当Spring容器启动完成会发布事件ContextRefreshedEvent,DubboDeployApplicationListener会监听这个事件,一旦接收到这个事件后,就会开始Dubbo的启动流程,就会执行DefaultModuleDeployer的start()进行服务导出(服务暴漏)与服务引入。
![]()


还记得serviceBean初始化的时候执行的afterPropertiesSet方法吗,会将ServiceBean加入到dubbo的configsCache缓存中,这里会取出来挨个进行服务导出。

在这里会从configManager中获取references进行服务的引用,也就是生成具体的远程调用代理类,最终会调用到referenceConfig中的init方法,ref就是生成的代理对象,也就是实际的业务执行者。




![]()
三、服务调用
当进行服务调用的时候此时的demoService其实就是ReferenceBean.getObject()方法返回的lazyProxy对象,执行方法调用时会通过createObject然后getCallProxy获取到执行业务的对象。


最终会来到referenceConfig.get()方法,由于ref属性已经在dubbo启动的时候通过referServices初始化完成,所以这里已经不是null了,最终调用该ref执行业务逻辑的调用。

至此、Dubbo整合spring的大致启动流程结束,下个章节解析Dubbo的服务暴漏与注册。
相关文章:
Dubbo源码解析(三)
一、Dubbo整合Spring启动流程 Dubbo的使用可以不依赖Spring,但是生产环境中Dubbo都是整合到Spring中一起使用,所以本章就解析Dubbo整合Spring的启动流程 一、传统的xml解析方式 一、Dubbo配置解析流程 在Java 中,一切皆对象。在JDK 中使用…...
HarmonyOS Next星河版笔记--界面开发(5)
1.字符串 1.1.字符串拼接 作用:把两个或多个字符串,拼成一个字符串。(通常是用来拼接字符串和变量) hello world > helloworld 加好作用:拼接 let name:string 小明 console.log(简介信息,名字是 name) …...
Spring Boot3 实战案例合集上线了
Spring Boot3实战案例合集...
在Ubuntu 24.04 LTS上安装飞桨PaddleX
前面我们介绍了《在Windows用远程桌面访问Ubuntu 24.04.1 LTS》本文接着介绍安装飞桨PaddleX。 PaddleX 3.0 是基于飞桨框架构建的一站式全流程开发工具,它集成了众多开箱即用的预训练模型,可以实现模型从训练到推理的全流程开发,支持国内外多…...
Homebrew 命令大全
Homebrew 是 macOS 和 Linux 系统上的一个流行的包管理器,它可以帮助用户轻松地安装、更新和管理软件包。以下是一些常用的 Homebrew 命令: 安装 Homebrew 如果你还没有安装 Homebrew,可以使用以下命令在 macOS 上进行安装: /b…...
Docker+Django项目部署-从Linux+Windows实战
一、概述 1. 什么是Docker Docker 是一个开源的应用容器引擎,支持在win、mac、Linux系统上进行安装。可以帮助我们在一台电脑上创建出多个隔离的环境,比传统的虚拟机极大的节省资源 。 为什么要创建隔离的环境? 假设你先在有一个centos7.…...
前端 JS 实用操作总结
目录 1、重构解构 1、数组解构 2、对象解构 3、...展开 2、箭头函数 1、简写 2、this指向 3、没有arguments 4、普通函数this的指向 3、数组实用方法 1、map和filter 2、find 3、reduce 1、重构解构 1、数组解构 const arr ["唐僧", "孙悟空&quo…...
11.15 机器学习-集成学习方法-随机森林
# 机器学习中有一种大类叫**集成学习**(Ensemble Learning),集成学习的基本思想就是将多个分类器组合,从而实现一个预测效果更好的集成分类器。集成算法可以说从一方面验证了中国的一句老话: # 三个臭皮匠,…...
【SQL】E-R模型(实体-联系模型)
目录 一、介绍 1、实体集 定义和性质 属性 E-R图表示 2. 联系集 定义和性质 属性 E-R图表示 一、介绍 实体-联系数据模型(E-R数据模型)被开发来方便数据库的设计,它是通过允许定义代表数据库全局逻辑结构的企业模式…...
C/C++静态库引用过程中出现符号未定义的处理方式
问题背景: 在接入新库(静态库)时遇到了符号未定义问题,并发现改变静态库的链接顺序可以解决问题。 问题根源: 静态库是由 .o 文件拼接而成的,链接静态库时,链接器以 .o 文件为单位进行处理。链接…...
『VUE』27. 透传属性与inheritAttrs(详细图文注释)
目录 什么是透传属性(Forwarding Attributes)使用条件唯一根节点禁用透传属性继承总结 欢迎关注 『VUE』 专栏,持续更新中 欢迎关注 『VUE』 专栏,持续更新中 什么是透传属性(Forwarding Attributes) 在 V…...
借助Excel实现Word表格快速排序
实例需求:Word中的表格如下图所示,为了强化记忆,希望能够将表格内容随机排序,表格第一列仍然按照顺序编号,即编号不跟随表格行内容调整。 乱序之后的效果如下图所示(每次运行代码的结果都不一定相同&#x…...
数据结构 ——— 层序遍历链式二叉树
目录 链式二叉树示意图编辑 何为层序遍历 手搓一个链式二叉树 实现层序遍历链式二叉树 链式二叉树示意图 何为层序遍历 和前中后序遍历不同,前中后序遍历链式二叉树需要利用递归才能遍历 而层序遍历是非递归的形式,如上图:层序遍历的…...
使用 Prompt API 与您的对象聊天
tl;dr:GET、PUT、PROMPT。现在,可以使用新的 PromptObject API 仅使用自然语言对存储在 MinIO 上的对象进行总结、交谈和提问。在本文中,我们将探讨这个新 API 的一些用例以及代码示例。 赋予动机: 对象存储和 S3 API 的无处不在…...
SpringBoot整合Mybatis-Plus实践汇总
相关依赖 MyBatis-Plus涉及的依赖主要是Mybatis-start、和分页插件的依赖,不考虑使用额外分页插件的前提下,只需要mybatis-plus-boot-starter一个依赖即可与SpringBoot集成: <!--Mybatis-plugs--><dependency><groupId>co…...
基于Spring Boot的在线性格测试系统设计与实现(源码+定制+开发)智能性格测试与用户个性分析平台、在线心理测评系统的开发、性格测试与个性数据管理系统
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...
Python实现人脸识别算法并封装为类库
引言 人脸识别技术在现代社会中应用广泛,从安全监控到智能门锁,再到社交媒体中的照片标记功能,都离不开这项技术。本文将详细介绍如何使用Python实现基本的人脸识别算法,并将其封装为一个类库,以便在多个项目中复用。…...
uniapp小程序分享使用canvas自定义绘制 vue3
使用混入结合canvas做小程序的分享 在混入里面定义一个全局共享的分享样式,在遇到特殊页面需要单独处理 utils/share.js import { ref } from vue; export default {onShow() {// 创建时设置统一页面的默认值uni.$mpShare {title: 分享的标题,path: /pages/home/…...
SpringCloud核心组件(四)
文章目录 NacosNacos 配置中心1.起源2.基本概念ProfileData IDGroup 3.基础配置a. bootstrap.ymlb. application.ymlc. nacos 中的配置 DataIDd.测试读取配置中心配置内容 4.配置隔离a.命名空间b.DataIDc.bootstrap.ymld.service 隔离 5.配置拆分a.配置拆分策略b.DataID 配置c.…...
如何把本地docker 镜像下载用到centos系统中呢?
如果需要将镜像下载到本地或在 CentOS 系统上使用该镜像,你可以按照以下步骤操作: 1. 拉取镜像 如果想将镜像从 Docker Hub 或其他镜像仓库下载到本地,可以使用 docker pull 命令。 如果使用的是本地构建的镜像(如 isc:v1.0.0&…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
基于Docker Compose部署Java微服务项目
一. 创建根项目 根项目(父项目)主要用于依赖管理 一些需要注意的点: 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件,否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

