基于dubbo 2.7.8分析。
对应着xml配置的<dubbo:service>和<dubbo:reference>,注解是@DubboService和@DubboReference。
注:2.7.7开始才增加这两个注解,之前使用的是@Service和@Reference。因为有开发者提议这个@Service和Spring中的@Service太容易混淆,建议调整为 @DubboService 和 @DubboReference。@Reference和@Service Naming issues
注解处理逻辑大致分两部分:
- 将所有 @DubboService 的 class 提升为 Spring bean。
- 为使用 @DubboReference 注解的字段或方法注入代理对象。
DubboComponentScanRegistrar
image.png当用户使用注解 @DubboComponentScan 时(@EnableDubbo的scanBasePackages), 会激活 DubboComponentScanRegistrar,其中registerBeanDefinitions 方法会注册 ServiceAnnotationBeanPostProcessor 和 ReferenceAnnotationBeanPostProcessor两种bean。通过名称很容易知道分别是处理服务注解和消费注解。
ServiceAnnotationBeanPostProcessor
ServiceAnnotationBeanPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 接口,Spring 容器中所有Bean注册之后会回调 postProcessBeanDefinitionRegistry 方法开始扫
描@DubboService 注解并注入容器。
image.png
1:Dubbo框架首先会提取用户配置的扫描包名称, 因为包名可能使用${...}占位符, 因此框架会调用 Spring 的占位符解析做进一步解码。
2:开始真正的注解扫描, 委托 Spring 对所有符合包名的.class文件做字节码分析, 最终通过 3 的配置扫描 @DubboService 注解作为过滤条件。在
4 中将 @DubboService 标注的服务提升为bean。
5:主要将 @DubboService 标注的服务创建BeanDefinitionHolder,用于后续生成 ServiceBean 定义。
6:注册 ServiceBean 定义并做属性绑定。ServiceBean 主要作用Spring启动后的服务暴露,每一个服务都会对应一个ServiceBean,主要封装的服务的一些标签属性如 interfaceClass、methods、retries等。
消费注解注入
在实际使用过程中,可能会在 @DubboService 注解的服务中注入@DubboReference注解, 这样就可以很方便地发起远程服务调用, Dubbo中做属性注入是通过 ReferenceAnnotationBeanPostProcessor 处理的, 主要做以下几种事情:
(1) 获取类中标注的 @DubboReference 注解的字段和方法。
(2) 反射设置字段或方法对应的引用。
ReferenceAnnotationBeanPostProcessor
image.pngimage.png
ReferenceAnnotationBeanPostProcessor 实现了
InstantiationAwareBeanPostProcessor 接口,所以在 Spring 的 Bean 中初始化前会触发 postProcessPropertyValues 方法, 该方法允许我们做进一步处理,比如增加属性和属性值修改等。
在 1 中主要利用这个扩展点查找服务引用的字段或方法。 在 2 中触发字段或反射方法值的注入, 字段处理会调用 findFieldAnnotationMetadata方法, 在 3 中会遍历类所有字段,(方法级别注入最终会调用 findAnnotatedMethodMetadata 方法处理上面的注解)。 在 2 中会触发字段或方法 inject, 这里做注入用的是
ReferenceBean类,它继承自 ReferenceConfig,在此基础上增加了 Spring初始化等生命周期方法, 比如触发afterPropertiesSet从容器中获取一些配置(protocol)等, 当设置字段值的时候仅调用 referenceBean.getObject()获取远程代理即可。
网友评论