dubbo在初始化的时候,充分利用了spring的扩展点,进行初始化,这篇笔记主要记录dubbo是如何利用spring的扩展点来进行初始化的;
这篇笔记只记录dubbo启动的时候的源码,不记录启动过程中服务导出和服务引入的源码
dubbo关键类
@DubboComponentScan
DubboComponentScanRegistrar
ServiceAnnotationBeanPostProcessor
ReferenceAnnotationBeanPostProcessor
ServiceBean
ReferenceBean
@Service
@Reference
dubbo在进行服务导出和服务引入之前,需要将对应的bean放入到spring容器中,比如:当前在UserService中引入了一个TestService,同时对外提供了一个OrderService的类
那dubbo在启动的时候,会扫描将加了@Service的OrderService先注入到spring的容器中,在spring容器启动完成之后,再去zk进行服务注册
同理在初始化UserService的时候,会对@Reference修饰的变量 TestService进行注入,注入的时候,就会去zk拉取对应的服务提供者,然后生成代理对象,将代理对象注入到UserService中
结论
1.在@DubboComponentScan注解中会import一个DubboComponentScanRegistrar,这个DubboComponentScanRegistrar是ImportBeanDefinitionRegistry的实现类
2.在其registerBeanDefinitions方法中会注入两个bean:ReferenceAnnotationBeanPostProcessor和ServiceAnnotationBeanPostProcessor
3.ServiceAnnotationBeanPostProcessor是BeanDefinitionRegistryPostProcessor的实现类,所以在其postProcessorBeanDefinitionRegistry()方法中,会调用dubboClassPathBeanDefinitionScanner的scan方法,进行扫描,将加了@Service注解的bean扫描到beanDefinitionMap中
添加到beanDefinitionMap中的时候,有一个点需要特别注意的是:对于dubbo的@Service注解所修饰的bean,在spring的beanDefinitionMap中,会有两个会beanDefinition,一个是正常的beanDefinition,可以理解为和spring扫描的bean是无差别的,另外一个beanDefinition的beanClass被设置为ServiceBean,这个我觉得和Mybatis的接口在被注入到beanDefinitionMap中的时候有点类似
在初始化bean的时候,如果整个spring容器刷新完成了,serviceBean会监听对应的事件,在监听到之后,开始进行服务导出的处理,这时候,调用的就是dubbo中的代码,完成:在zk中注册服务、开启netty等
3.ReferenceAnnotationBeanPostProcessor是一个后置处理器,会对加了@Reference注解的bean进行处理,如果A这个类中通过@Reference注入了bean,在注入的时候,会被这个后置处理器处理
在一个bean初始化的过程中,会进行属性注入,调用其inject方法,然后在inject方法中,会对要注入的bean进行处理,将referenceClass,也就是要注入的bean,包装成referenceBean,然后调用referenceBean的getObject()方法进行服务引入,在referenceBean.getObject()方法中,返回的是一个代理对象,在其getObject()方法中,会开启完成服务引入,然后在属性注入的时候,注入的就是一个代理对象
源码
@DubboComponentScan
这个注解如果陌生的话,那@EnableDubbo这个注解应该不会陌生
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
}
我们就直接来看@DubboComponentScan这个注解了
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(DubboComponentScanRegistrar.class)
public @interface DubboComponentScan {
}
DubboComponentScanRegistrar
可以看到,在其注解上,通过@Import注解,引入了这个类,这个类是ImportBeanDefinitionRegistrar的实现类,关于ImportBeanDefinitionRegistrar这个扩展点,在前面@Import原理
中有介绍过,这个也是spring的扩展点之一,在初始化的过程中,会调用ImportBeanDefinitionRegistrar实现类的registerBeanDefinitions()方法,
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
reg