[Dubbo3源码系列]-springboot装配dubbo源码分析

63 阅读2分钟

本篇文章主要是描述dubbo是如何被spring容器管理的,所以需要你有一定spring容器等源码知识和dubbo的使用经验。spring容器管理dubbo bean,也可以拆解以下问题

  1. dubbo bean如何被识别扫描到的?
  2. duboo bean如何注入到BeanDefinition中的?
  3. dubbo 服务是如何导出和引用的?

请大家带着上述问题看下面描述。

Dubbo声明

一切的起源,在启动类上使用注解@EnableDubbo,声明dubbo

@SpringBootApplication
@EnableDubbo(scanBasePackages = {"org.example"})
public class Main {
    public static void main(String[] args) throws InterruptedException {
        ConfigurableApplicationContext context = SpringApplication.run(Main.class, args);
        CircleAService circleAService = (CircleAService) context.getBean("circleAService");
        System.out.println(circleAService.invoke());
        new CountDownLatch(1).await();
    }
}

@EnableDubbo注解会引入两个Registrar类,DubboConfigConfigurationRegistrarDubboComponentScanRegistrar

@EnableDubbo@EnableDubboConfig@DubboComponentScan
image.pngimage.pngimage.png

所以在SpringApplication.run处理方法中会 调用invokeBeanDefinitionRegistryPostProcessors中会执行上述两类方法。DubboConfigConfigurationRegistrar会初始化dubbo的context,为dubbo添加Bean实例和注册BeanDefinition,具体类如下表。

DubboRegistrar添加的singletonObject添加的BeanDefinition
DubboConfigConfigurationRegistrar1. DubboSpringInitContext
2. ApplicationMode
3. ModuleModel
1. ServicePackagesHolder
2. DubboContextPostProcessor
3. ReferenceBeanManager
4. ReferenceAnnotationBeanPostProcessor
5. DubboConfigAliasPostProcessor
6. DubboDeployApplicationListener
7. DubboConfigApplicationListener
8. DubboConfigDefaultPropertyValueBeanPostProcessor
9. DubboConfigBeanInitializer
10. DubboInfraBeanRegisterPostProcessor
DubboComponentScanRegistrar1. ServiceAnnotationPostProcessor

Dubbo BeanDefinition注册

前面陈述了一堆,也列举了一堆类。心切的你肯定想问这和dubbo bean的扫描加载有啥关系,此时你可以重点关注两个类ServiceAnnotationPostProcessorReferenceAnnotationBeanPostProcessor

  1. ServiceBean注册
    ServiceAnnotationPostProcessor 是一个BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor类。
    所以在springContext的refresh过程中,invokeBeanDefinitionRegistryPostProcessors方法会执行ServiceAnnotationPostProcessor的postProcessBeanDefinitionRegistry方法。该方法中会创建DubboClassPathBeanDefinitionScanner类扫描@DubboService的注解类,并将该类注册到BeanDefinitionMap中。
    同时也会创建一个以@DubboService的注解类为属性的ServiceBean,并将该ServiceBean注册到BeanDefinitionMap中。生成的ServiceBeanDefinition默认为非懒加载

ServiceAnnotationPostProcessor#processScannedBeanDefinition

image.png

所以针对@DubboService的注解类会注入两个BeanDefinition

  1. ReferenceBean 注册

会调用ReferenceAnnotationBeanPostProcessor中的postProcessBeanFactory方法,通过判断BeanDefinition的属性是否有引用@DubboReference,若有则进行注册ReferenceBean。

如下图Main类通过@DubboReference引用了dubbo类,通过ReferenceAnnotationBeanPostProcessor可以识别出Main类存在@DubboReference引用,并为引用的类生成一个BeanDefinition。

Main中引用ReferenceReferenceAnnotationBeanPostProcessor 实际注入地方

注册后的BeanDefinition,该BeanDefinition也是非懒加载

Dubbo Bean加载

spring的ApplicationContext#refresh会将非懒加载的bean进行加载,具体方法见finishBeanFactoryInitialization,由于dubbo的serviceBean和ReferenceBean 都不是懒加载,所以此时会对这些BeanDefinition进行加载。

在ServiceBean中的afterPropertiesSet方法中,会将本ServiceBean添加到ConfigManager中

ReferenceBean中的afterPropertiesSet方法中,同样会自己添加到referenceBeanManager中

Dubbo 导出及引用

  1. Service导出

spring启动后的AbstractApplicationContext#finishRefresh会进行publishEvent,该事件会触发DubboDeployApplicationListener执行onContextRefreshedEvent方法,最终会执行exportServiceInternal来进行服务导出

  1. Reference引用

和Service导出一样,org.apache.dubbo.config.deploy.DefaultModuleDeployer#referServices 会对referService进行引用