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&…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
MySQL的pymysql操作
本章是MySQL的最后一章,MySQL到此完结,下一站Hadoop!!! 这章很简单,完整代码在最后,详细讲解之前python课程里面也有,感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...
sshd代码修改banner
sshd服务连接之后会收到字符串: SSH-2.0-OpenSSH_9.5 容易被hacker识别此服务为sshd服务。 是否可以通过修改此banner达到让人无法识别此服务的目的呢? 不能。因为这是写的SSH的协议中的。 也就是协议规定了banner必须这么写。 SSH- 开头,…...

