Dubbo第四天

6 Dubbo 启动过程探析

6.1 Spring 简介 BeanDefinition

在 Java 中,一切皆对象。在 JDK 中使用 java.lang.Class 来描述类这个对象。

而在 Spring 中,bean 对象是操作核心。那么 Spring 也需要一个东西来描述bean 这个对象,它就是 BeanDefinition。

有兴趣的同学,可以详细追一下 spring 的基础流程,其整体类图如下:

详细的 spring 原理不属于本课的内容,这里只回顾下 BeanDefinition 的基础用法:

RootBeanDefinition beanDef = new RootBeanDefinition();


beanDef.setBeanClass(DemoServiceImpl.class);

beanDef.setBeanClassName(DemoServiceImpl.class.getName());

beanDef.setScope(BeanDefinition.SCOPE_SINGLETON);//单例


//设置属性

MutablePropertyValues propertyValues = beanDef.getPropertyValues();

propertyValues.addPropertyValue("type","runtime");


//注册 bean

applicationContext.registerBeanDefinition("demoService", beanDef);

可以看到,最后的 spring 动作 applicationContext.registerBeanDefinition 会在 IOC容器内创建描述的 bean 对象。具体验证可参见 demo 代码后续 Dubbo 的所有对象创建,皆以此形式委托给 Spring 来创建。

6.2Dubbo 的配置解析过程

dubbo 的配置解析,不论是 xml 方式的配置,还是注解的配置,目标都是把配置的属性值提取出来,变成 dubbo 的组件 bean(先由BeanDefinition 描述,然后委托 spring 生成组件 bean)。

下面以 xml 的标签为例,列出每种配置对应要解析成为的目标组件 bean:

6.2.1 xml 配置的解析过程

首先,dubbo 自定义了 spring 标签描述 dubbo.xsd。在 dubbo-config-spring模块下的 src/main/resouce/META-INF 下。

其次,在 spring.handlers、spring.schemas 中指定解析类,将标签引入 spring 中管理。

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

6.2.2 注解的解析过程

Dubbo 注解的目标,与 xml 一致,都是将配置信息变为 BeanDefinition定义,交由 spring 生成组件 bean。

注解的源头是@EnableDubbo 用于启用 dubbo 配置。而此注解又引入EnableDubboConfig 和 DubboComponentScan 注解。

其中,@EnableDubboConfig 主要用于处理 dubbo 中全局性的组件配置,一般在.properties 文件中的配置项,如Application/Registry/Protocol/Provider/consumer ,而@DubboComponentScan 负责扫描项目源代码,处理业务类上的Reference/Service 注解。

6.2.2.1@EnableDubboConfig 的过程

@EnableDubboConfig 主要用来解析属性文件中的配置,一般在springboot 项目中比较常用,过程如下:

通过 DubboConfigConfigurationSelector 类,连接到DubboConfigConfiguration 类,此处配置了它支持解析的所有注解组件,如下:

此处为每个 dubbo 组件绑定了属性文件的前缀值。

具体的处理过程在:@EnableDubboConfigBinding 中,最终引入到DubboConfigBindingRegistrar 类来完成组件 bean 注册。

6.2.2.2@DubboComponentScan 的过程

DubboComponentScan 用来解析,标注在业务 Service 实现上的注解,主要是暴露业务服务的@Service 和引入服务的@Reference。总入口在DubboComponentScanRegistrar 上。可以看到,两个注解的处理是分开处理的。

6.2.2.2.1 service 注解

service 注解的处理,最终由 serviceAnnotationBeanPostProcessor 来处理。整个过程比较简单,dubbo 先调用 spring 扫描包处理:

此处,先由 spring 将暴露的业务服务实例化。然后再创建 dubbo 的组件对象。

servicebean 有很多父级组件信息引入,这些组件已经在属性文件处理部分完成。servicebean 中将 ref 指向业务 bean。

6.2.2.2.2 reference 注解

reference 注解的处理,最终由 ReferenceAnnotationBeanPostProcessor 来处理。

ReferenceAnnotationBeanPostProcessor 继承于 AnnotationInjectedBeanPostProcessor 实现了 MergedBeanDefinitionPostProcessor 接口,方法 postProcessMergedBeanDefinition在创建 bean 实例前会被调用(用来找出 bean 中含有@Reference 注解的 Field 和 Method)。

然后使用这一句 metadata.inject(bean, beanName, pvs)对字段和方案进行反射绑定。

当 Spring 完成 bean 的创建后会调用 AbstractAutowireCapableBeanFactory#populateBean 方法完成属性的填充。

6.3Dubbo 的服务暴露过程

前面已经看到,dubbo 的组件中,servicebean 和 referencebean 是比较特殊的。这两个组件,将完成 dubbo 服务的远程 rpc 过程。

servicebean 作为服务端,会在 bean 创建成功后,发起服务暴露流程。其过程如下:

在实现的 InitializingBean 接口中,spring 调用afterPropertiesSet 方法,发起服务的暴露动作。

父类中最终执行此动作:

先将本地服务 ref 包装成 invoker,然后由 protocol 网络协议将invoker 连通到网络上。其核心,即是一旦有 protocol 网络传输过来的请求,则拉起 invoker 动作,并将动作传递到 ref 服务上进行响应。

在这个整个过程中,dubbo 不希望每一个具体的协议 ptotocol 去关心目标服务是谁(耦合性太强),于是中间插入了一个 invoker 概念实体来解耦双方的绑定关系(重点)。

为了详细说明白这个过程,我们细细探究看一下 invoker 的机理:

 首先,明确目标,invoker 的本义,是 invoke 方法会转嫁对象到目标 ref 上(具体怎么转嫁,后续会演示),接口定义如下:

 协议使用方,希望如此调用 invoker:

意思是,希望 dubbo 中的所有协议都按此模式,将网络请求转给 invoker对象即可,剩下的 protocol 协议不要去关心。

 Invoker 如何转请求到 target 目标服务呢?

交给 Invoker 的实现类去具体实现,下面是个例子,invoker 中本身持有目标 target 服务:

后续的调用不言自明,肯定是通过 java 反射将方法转给 target 服务。

 总结上述过程:

1、protocol 组件收到网络请求到来时,它需要将请求发向 target 目标服务(如果当前环境中有此服务就好了)。

2、因为当前环境中没有 target 对象,于是它创建了一个 target 的代理对象 proxy,将请求转给了此代理 proxy 对象,而此 proxy 对象只会干一件事,将调用甩锅给了 invoker 对象的 invoke 方法。

3、invoker 对象发现自己内部有 target 对象,调用 so easy,于是它使用 java 反射,将请求发向了 target 服务。

PS:我们可以想到,如果让 protocol 中持有 target 服务,直接转向请求到 target 要简单得多,但这样一来,每一个 ptotocol 服务要对接千千万万的业务 service 接口,耦合性太强。于是,dubbo 专门设计了invoker 实体来解开两者间的直接耦合(工作中可否借鉴?)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容