Dubbo的版本是基于 2.7.3.Release
首先还是通过配置EnableDubbo注解开启Dubbo,配置扫描Bean的basePackage,由于是消费端是注册@Reference的Bean

简单配置@Reference注解引用提供者的接口,可以实现对远程提供者的方法的调用.接下来分析消费端启动加载流程

@EnableDubbo是注解上同时配置了@DubboComponentScan注解,

DubboComponentScanRegistrar中registerServiceAnnotationBeanPostProcessor注册@Service的BeanProcessor(扫描并注册服务提供者ServiceBean),registerReferenceAnnotationBeanPostProcessor的含有@Reference注解的服务消费者的BeanProcessor(主要将注入的接口转换成ReferenceBean注入Spring容器).

可以从下图看到注入Spring的容器的Bean的Definiiton的name属性是referenceAnnotationBeanPostProcessor,beanClass属性是ReferenceAnnotationBeanPostProcessor.

下面看下ReferenceAnnotationBeanPostProcessor的类的结构图,右边总体上看是实现BeanProcessor接口,同时有很多其他增加接口,左边则主要是实现 Aware接口(用来注入的抽象接口),同时还是实现了ApplicationListener接口
(用户监听ContextRefreshedEvent和ServiceBeanExportedEvent事件).

AnnotationInjectedBeanPostProcessor是ReferenceAnnotationBeanPostProcessor的父类,它实现InstantiationAwareBeanPostProcessorAdapter的postProcessPropertyValues方法,这个是实例化的后置处理,这个方式是在注入属性时触发,就是要在注入@Reference的接口时候,要将接口封装成动态代理的实例注入到Spring容器中.

这里可以看到通过findInjectionMetadata方法找InjectionMetadata注入的元数据信息,然后调用inject方法注入bean中属性.

通过bean的名字缓存注解的元信息AnnotatedInjectionMetadata,如果重新
build构建注解的元数据信息.

AnnotatedInjectionMetadata是找bean容器实例中Field和Method的注解的元信息.

这里看下其中的findFieldAnnotationMetadata,查找Field带有@Reference注解的元数据信息,其中getAnnotation就是获取@Reference注解,然后封装成 AnnotatedFieldElement的集合返回,findAnnotatedMethodMetadata也是一样查找方法带有@Reference的元信息.

上面已经提到,获取AnnotatedFieldElement的集合,最终会调用inject方法注入Bean的属性. 首先,获取带有@Reference注解Field的Class的类型,然后调用getInjectedObject得到注入的真实实例,

首先构建缓存的key,cacheKey的生成规则:ServiceBean:interfaceName:version:group, 缓存为空,则走doGetInjectedBean获取实例对象的逻辑,其实就是创建的动态代理,

ReferenceAnnotationBeanPostProcessor的doGetInjectedBean方法获取实例的获取动态代理逻辑,首先,buildReferencedBeanName生成BeanDefinition中的name为referencedBeanName,然后通过buildReferenceBeanIfAbsent构建ReferenceBean,然后通过buildProxy创建动态代理.

首先从缓存中通过referenceBeanName查找已将缓存的bean, 没有就通过
ReferenceBeanBuilder通过建造者模式构建一个ReferenceBean实例

buildProxy方法通过buildInvocationHandler方法创建ReferenceBeanInvocationHandler是实现JDk的InnvokeHandler,可以看出此处是用的JDK的动态代理,如果applicationContext已经有applicationContext没有referencedBeanName消费者的bean,则调用ReferenceBeanInvocationHandler的init()方法,并调用referenceBean的get方法,

接下来的是ReferenceBean中的get方法,如果ref就是代理对象,如果是空的,调用init方法,

这里最终要一步就是ref是创建的代理对象.

createProxy首先判断是否是JVM内部的refer,如果是在同一个JVM中,
则调用REF_PROTOCOL.refer转换成invoker,如果不是从注册元信息url中解析成多个URL保存到urls中.

下面createProxy的下半部分,首先判断注册信息url的URL的size大小是否只有一个,如果是单注册中心, 则直接调用DubboProtocol的refer
将URL和interface转换成Invoker对象,如果是多注册中心,则循环调用
dubboProtocol的refer生成invoker的集合,通过Cluster实例的join方
法转换成一个invoker, 最后调用ProxyFactory的getProxy方法生成代
理对象,

默认是JavassistProxyFactory的getProxy生成的代理对象,通过
实现InvokerInvocationHandler是实现JDK的InvocationHandler接口,Proxy则是dubbo自己实现的代理类(这个后面详细分析下),

最后看下InvokerInvocationHandler的invoker的方法,这个是通过 @Reference注入的代理对象被调用时,则会执行invoke方法,可以看出
这个是通过调用invoker实例的invoke传入的RpcInvocation对象(主要包含方法名和参数),然后调用recreate重新组装rpc调用结果.
总结
今天主要分析消费者的启动过程分析,以及调用链路分析,其中还有很多细节没有梳理清楚,后面后对调用远程过程做更加详细的分析.