本篇文章主要是描述dubbo是如何被spring容器管理的,所以需要你有一定spring容器等源码知识和dubbo的使用经验。spring容器管理dubbo bean,也可以拆解以下问题
- dubbo bean如何被识别扫描到的?
- duboo bean如何注入到BeanDefinition中的?
- 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类,DubboConfigConfigurationRegistrar 和 DubboComponentScanRegistrar。
| @EnableDubbo | @EnableDubboConfig | @DubboComponentScan |
|---|---|---|
所以在SpringApplication.run处理方法中会 调用invokeBeanDefinitionRegistryPostProcessors中会执行上述两类方法。DubboConfigConfigurationRegistrar会初始化dubbo的context,为dubbo添加Bean实例和注册BeanDefinition,具体类如下表。
| DubboRegistrar | 添加的singletonObject | 添加的BeanDefinition |
|---|---|---|
| DubboConfigConfigurationRegistrar | 1. 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 |
| DubboComponentScanRegistrar | 1. ServiceAnnotationPostProcessor |
Dubbo BeanDefinition注册
前面陈述了一堆,也列举了一堆类。心切的你肯定想问这和dubbo bean的扫描加载有啥关系,此时你可以重点关注两个类ServiceAnnotationPostProcessor和ReferenceAnnotationBeanPostProcessor
- ServiceBean注册
ServiceAnnotationPostProcessor 是一个BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor类。
所以在springContext的refresh过程中,invokeBeanDefinitionRegistryPostProcessors方法会执行ServiceAnnotationPostProcessor的postProcessBeanDefinitionRegistry方法。该方法中会创建DubboClassPathBeanDefinitionScanner类扫描@DubboService的注解类,并将该类注册到BeanDefinitionMap中。
同时也会创建一个以@DubboService的注解类为属性的ServiceBean,并将该ServiceBean注册到BeanDefinitionMap中。生成的ServiceBeanDefinition默认为非懒加载。
ServiceAnnotationPostProcessor#processScannedBeanDefinition
所以针对@DubboService的注解类会注入两个BeanDefinition
- ReferenceBean 注册
会调用ReferenceAnnotationBeanPostProcessor中的postProcessBeanFactory方法,通过判断BeanDefinition的属性是否有引用@DubboReference,若有则进行注册ReferenceBean。
如下图Main类通过@DubboReference引用了dubbo类,通过ReferenceAnnotationBeanPostProcessor可以识别出Main类存在@DubboReference引用,并为引用的类生成一个BeanDefinition。
| Main中引用Reference | ReferenceAnnotationBeanPostProcessor 实际注入地方 |
|---|---|
注册后的BeanDefinition,该BeanDefinition也是非懒加载
Dubbo Bean加载
spring的ApplicationContext#refresh会将非懒加载的bean进行加载,具体方法见finishBeanFactoryInitialization,由于dubbo的serviceBean和ReferenceBean 都不是懒加载,所以此时会对这些BeanDefinition进行加载。
在ServiceBean中的afterPropertiesSet方法中,会将本ServiceBean添加到ConfigManager中
ReferenceBean中的afterPropertiesSet方法中,同样会自己添加到referenceBeanManager中
Dubbo 导出及引用
- Service导出
spring启动后的AbstractApplicationContext#finishRefresh会进行publishEvent,该事件会触发DubboDeployApplicationListener执行onContextRefreshedEvent方法,最终会执行exportServiceInternal来进行服务导出
- Reference引用
和Service导出一样,org.apache.dubbo.config.deploy.DefaultModuleDeployer#referServices 会对referService进行引用