dubbo源码分析8(服务消费者之生成代理对象)

前面几篇博客,说了很多dubbo服务提供者相关的流程;

复习一下:首先服务提供者去暴露服务接口数据到注册中心,然后本地启动netty服务端监听是否有消费者的请求,现在我们可以看看消费者端是怎么从注册中心获取指定的接口信息, 然后访问netty服务端,就行了;

提前须知:要提前了解spring的ioc容器初始化的过程以及调用ioc容器的getBean的逻辑,这个不是我们的重点

1 准备工作

我们先大概看看服务消费者大概做了些什么事情,打开消费者端的demo,下图所示,首先是初始化spring的ioc容器,然后从容器中获取实例bean, 然后调用该bean的方法

dubbo源码分析8(服务消费者之生成代理对象)

结合我们知道的spring的知识,我们就大胆的猜测一下,在spring的ioc初始化的过程中,会解析我们配置在xml文件中

这里消费者端初始化ioc容器的时候,和服务提供者一样,都是在DubboBootstrap的start方法开始发车,这个start方法里面会调用exportServices()方法暴露服务和referServices()引用服务,因为一个服务既可以是服务提供者,同时也可以是服务消费者,这个不难理解吧!比如A->B->C, B服务对A来说是服务提供者, 对C来说是服务消费者

dubbo源码分析8(服务消费者之生成代理对象)

dubbo源码分析8(服务消费者之生成代理对象)

然后就是spring的逻辑了,在从ioc获取对象(也就是调用getBean方法)的时候,会判断这个对象ReferenceBean有没有实现FactoryBean接口,有的话,就调用FactoryBean的getObject方法

dubbo源码分析8(服务消费者之生成代理对象)

刚好我们去看看ReferenceBean类,巧了( ̄o ̄) . z Z,刚好实现了FactoryBean接口,于是就会调用下图的getObject()方法

dubbo源码分析8(服务消费者之生成代理对象)

总结一下,服务消费者就干了三件事:

(1)启动ioc容器进行初始化,初始化过程中对dubbo的配置文件进行解析

(2)从ioc容器获取bean的时候,调用getBean方法的时候,会判断当前的Bean是否实现了FactoryBean接口,有的话,就调用getObject方法生成代理对象,并放入ioc容器中

(3)调用代理对象的方法,这个方法内部封装了远程调用的细节,返回调用结果;

2.生成代理对象

这里默认大家都对spring的ioc容器的启动已经很熟悉了,就不再过多的描述,我们就看看是怎么生成代理对象的;

我们就从ReferenceBean的getObject方法开始出发,连续截图三张,我们可以看到调用了父类的ReferenceConfig的get()方法, 再之后就是调用init()方法进行初始化操作

dubbo源码分析8(服务消费者之生成代理对象)

dubbo源码分析8(服务消费者之生成代理对象)

这个init方法很长, 我们等下看看调用createProxy(xxx)方法的逻辑

dubbo源码分析8(服务消费者之生成代理对象)

2.1 创建代理对象

这个init方法百分之九十的代码都是设置参数到map里面,然后再根据这个map创建代理对象

dubbo源码分析8(服务消费者之生成代理对象)

下面都是createProxy方法内部比较重要的部分,总结一下其实就是干了几件事,首先就是判断引用的服务是本地注册还是远程注册, 如果是远程注册就继续判断有几个注册中心,如果只有一个注册中心的话,就去那个注册中心获取服务数据转为一个invoker就好了;

如果是多个注册中心,就将每个注册中心中的该服务信息多转为invoker, 再用cluster将多个invoker合并成一个统一的invoker;

最终就是调用代理工厂proxyFactory将invoker生成代理对象;

dubbo源码分析8(服务消费者之生成代理对象)

dubbo源码分析8(服务消费者之生成代理对象)

dubbo源码分析8(服务消费者之生成代理对象)

最终的根据代理工厂将invoker生成代理对象

dubbo源码分析8(服务消费者之生成代理对象)

现在基本流程我们知道了,首先看看是否有多个注册中心,因为一个服务可以同时注册到多个注册中心,这里会从多个注册中心中获取相同名字的服务, 然后再将这些服务合并成一个invoker,然后就是根据最后生成的invoker生成代理类

接下来我们继续看看REF_PROTOCOL.refer(xxx)生成invoker的逻辑,还有FROXY_FACTORY.getProxy(invoker)生成代理类,理解了这两个逻辑,就ok了;

2.2 REF_PROTOCOL.refer(xxx)生成invoker

由于现在只有一个注册中心,我们从这里进入开始看看怎么生成invoker的逻辑

dubbo源码分析8(服务消费者之生成代理对象)

首先获取到注册中心实例,根据我们的消费者端的信息,去注册中心里创建consumer节点,然后接下来就是订阅providers、configurators、routers 等节点数据,只要是这几个节点有数据变化,就会通知到消费者端

dubbo源码分析8(服务消费者之生成代理对象)

dubbo源码分析8(服务消费者之生成代理对象)

dubbo源码分析8(服务消费者之生成代理对象)

其实到这里就已经很清晰了, 不过在上图的第3步,就是用一个接口可能是集群部署的嘛,然后都注册到同一个注册中心中,我们需要将获取到的这个接口的多个服务提供者,然后又给聚合成一个invoker(其实这里的directory比较形象,中文意思是目录,这个目录下可能有多个服务提供者的呀)

3.FROXY_FACTORY.getProxy(invoker)生成代理对象

在上面我们已经从所有注册中心获取了所有实现了该接口的服务,最后合并成了一个invoker,然后就是根据这个invoker生成代理对象

在getProxy()方法里面,其实就是判断当前服务接口是不是一个泛化接口(可以去了解一下dubbo的泛化,就是另外一种调用接口的方式而已,可以不提供服务接口),如果是的话,就做特殊处理,否则就把代理对象直接返回

这里很明显就是直接返回代理对象

dubbo源码分析8(服务消费者之生成代理对象)

当代理对象生成出来了之后,后续的就跟dubbo没啥关系了, 就是spring的内容,将生成的代理对象放到ioc容器中,并该接口的全名称对应起来,只要是下次我们再去获取这个实例的时候,就直接从ioc容器中获取了

下图所示,可以看到是一个代理对象

dubbo源码分析8(服务消费者之生成代理对象)

可以看到最终的ioc容器中已经有个这个代理对象了

dubbo源码分析8(服务消费者之生成代理对象)

4.总结

服务消费者的逻辑会比较多,现在首先会根据你要调用的这个接口,去多个注册中心看看,而且每个注册中心相同的一个服务A还有可能有多个,我们最终就多个服务A给拼接成一个invoker

然后我们再使用代理工厂将这个invoker生成一个代理对象,并且和该服务接口名称对应起来放到spring的ioc容器中,下次再去获取这个接口的服务的时候,就能获取到这个代理对象了,这个代理对象中肯定是封装了netty远程调用的逻辑

下一篇我们看看是怎么进行远程调用,怎么拿到接口调用的返回值

Original: https://www.cnblogs.com/wyq1995/p/15807675.html
Author: java小新人
Title: dubbo源码分析8(服务消费者之生成代理对象)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/574188/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【系列文章】Maven 源码解析:依赖调解是如何实现的?

    系列文章目录(请务必按照顺序阅读): 给自己的公众号打个广告 欢迎大家关注我的公众号:xiaoxi666,一起来玩一起学! Original: https://www.cnblog…

    Java 2023年6月16日
    073
  • 和朱晔一起复习Java并发(二):队列

    和朱晔一起复习Java并发(二):队列 老样子,我们还是从一些例子开始慢慢熟悉各种并发队列。以看小说看故事的心态来学习不会显得那么枯燥而且更容易记忆深刻。 阻塞队列的等待? 阻塞队…

    Java 2023年5月29日
    087
  • 老生常谈系列之Aop–JDK动态代理的底层实现原理

    老生常谈系列之Aop–JDK动态代理的底层实现原理 前言 在Aop系列里面有两篇文章,分别是老生常谈系列之Aop–Spring Aop原理浅析和老生常谈系列…

    Java 2023年6月8日
    084
  • 【持久层框架】- SpringData-JPA

    SpringData – JPA 😄生命不息,写作不止🔥 继续踏上学习之路,学之分享笔记👊 总有一天我也能像各位大佬一样🏆 一个有梦有戏的人 @怒放吧德德🌝分享学习心得…

    Java 2023年6月16日
    098
  • 第二周总结-Spring学习

    java;gutter:true;</p> <h2>Spring_day01</h2> <p><strong>今日目标&…

    Java 2023年6月7日
    088
  • JAVA的变量与常量

    实践是唯一的真理。 变量 变量的定义 变量就是可以变化的量。 JAVA变量是程序中最基础的程序单元,其要素包括变量名,变量类型及作用域。 写程序要注意程序的可读性 如图所示,可以一…

    Java 2023年6月9日
    081
  • 微服务架构对企业来说,带来什么价值?有啥弊端?

    微服务架构,这 5 年左右一直被认可,是软件架构的未来方向。需要大家理解的是,为什么需要服务化。比如微服务架构对企业来说,带来什么价值?有啥弊端? 这里浅谈一下微服务架构,主要还是…

    Java 2023年6月13日
    074
  • Java 单例模式 饿汉式与懒汉式

    posted @2022-03-27 11:34 紫薇哥哥 阅读(5 ) 评论() 编辑 Original: https://www.cnblogs.com/ziweigege/p…

    Java 2023年6月5日
    089
  • 操作无权限的MSMQ队列

    首先,我们重现一个这样的”死”队列。在消息队列的管理器中新建一个队列(私有或公有均可),命名为test。右键单击该队列,选择Properties,然后进入S…

    Java 2023年5月30日
    066
  • spring-boot-导出excel-xlsx 文件损坏

    maven的pom文件处理 ①将resource标签配置如下 src/main/resources true bootstrap.yml **/*.xml **/excelTemp…

    Java 2023年6月9日
    067
  • 通过宿主主机访问部署在虚拟机上的网站

    网站部署在笔记本的虚拟机(CentOS 6.8)上,虚拟机通过桥接的方式联网,网站开启成功,在虚拟机上可以打开,但是在宿主的浏览器打不开,后面百度一下发现是虚拟机的防火墙导致的。关…

    Java 2023年5月30日
    068
  • Git

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月6日
    085
  • Java加糖,去苦留香

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年5月29日
    074
  • 后端开发学习记录(一)——Java语言的学习

    准备阶段 先学会IDEA的基本调试 插件目前在用的是汉化版,在熟悉后尽量使用英文版(现已改成英文版) 调节字体大小,行间距,注释的颜色要会 Java的基本语法 关于字节 强制转换 …

    Java 2023年6月13日
    065
  • java集合类的比较

    java集合类的比较 正文: 判断集合是否相等,使用org.apache.commons.collections包下 CollectionUtils.isEqualCollecti…

    Java 2023年6月7日
    071
  • 快速登陆linux服务器

    前言 本文适用于喜欢原生终端的用户,钟爱第三方ssh客户端的可以无视….客户端可以保存用户信息和密码,比较无脑。mac可以使用终端,win可以使用git的bash。 上…

    Java 2023年6月5日
    081
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球