Dubbo源码分析
1 注册Provider
1.1 构造ServiceBean
ServiceBean继承与ServiceConfig,构造完成,并注册后。在触发ServiceBean的onApplicationEvent事件后,进行dubbo意义上的provider注册zookeeper。一个ServiceBean就对应一个@Service的注解,注解的属性其实和在配置文件中是一致的。所以说,我们是可以做到每一个微服务接口,注册到不同的注册中心的。当然一般不会这么干。
首先dubbo使用ServiceAnnotationBeanPostProcessor实现spring的BeanDefinitionRegistryPostProcessor接口。
这个接口是用来注册在配置文件或者注解中配置的javaBean.
BeanDefinitionRegistryPostProcessor提供了让我们对BeanDefinition进行自定义注册的方法,如果Spring中的默认配置方式不能满足你的要求,就可以通过实现BeanDefinitionRegistryPostProcessor接口来进行扩展。(详情:http://rason.me/2016/12/16/BeanDefinitionRegistryPostProcessor/)
首先看下这个接口的方法:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}
这个方法实现后,spring传入BeanDefinitionRegistry(Bean 定义注册),然后并调用方法。只需要在其中写注册的bean的业务。在这里就要注册dubbo需要的什么protocol,service,provide等参数。
再看看实现:
private void registerServiceBeans(Set packagesToScan, BeanDefinitionRegistry registry) {
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
for (String packageToScan : packagesToScan) {
// Registers @Service Bean first
scanner.scan(packageToScan);
// Finds all BeanDefinitionHolders of @Service whether @ComponentScan scans or not.
Set beanDefinitionHolders =
findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
registerServiceBean(beanDefinitionHolder, registry, scanner);
}
通过DubboClassPathBeanDefinitionScanner进行扫描,配置注解的service类并注册他们,把scanner传递下去。然后从中过滤出带有@service注解的bean包装成BeanDefinitionHolder传递给registerServiceBean(beanDefinitionHolder, registry, scanner)方法。然后看看registerServiceBean做了什么。
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry,DubboClassPathBeanDefinitionScanner scanner) {
Class> beanClass = resolveClass(beanDefinitionHolder);
Service service = findAnnotation(beanClass, Service.class);
Class> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
String annotatedServiceBeanName = beanDefinitionHolder.getBeanName();
AbstractBeanDefinition serviceBeanDefinition =
buildServiceBeanDefinition(service, interfaceClass, annotatedServiceBeanName);
// ServiceBean Bean name
String beanName = generateServiceBeanName(service, interfaceClass, annotatedServiceBeanName);
if (scanner.checkCandidate(beanName, serviceBeanDefinition)) { // check duplicated candidate bean
registry.registerBeanDefinition(beanName, serviceBeanDefinition);
if (logger.isInfoEnabled()) {
logger.warn("The BeanDefinition[" + serviceBeanDefinition +
"] of ServiceBean has been registered with name : " + beanName);
}
} else {
通过上一步BeanDefinitionHolder解析出字节码对象,接口的字节码,bean的名字包装为AbstractBeanDefinition给BeanDefinitionRegistry(spring)进行注册。先来看看buildServiceBeanDefinition是怎么构造AbstractBeanDefinition的。
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
String[] ignoreAttributeNames = of(“provider”, “monitor”, “application”, “module”, “registry”, “protocol”, “interface”);
propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(service, environment, ignoreAttributeNames));
// References “ref” property to annotated-@Service Bean
addPropertyReference(builder, “ref”, annotatedServiceBeanName);
// Set interface
builder.addPropertyValue(“interface”, interfaceClass.getName());
/**
* Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference
*/
String providerConfigBeanName = service.provider();
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, “provider”, providerConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference
*/
String monitorConfigBeanName = service.monitor();
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, “monitor”, monitorConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference
*/
String applicationConfigBeanName = service.application();
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, “application”, applicationConfigBeanName);
}
/**
* Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference
*/
String moduleConfigBeanName = service.module();
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, “module”, moduleConfigBeanName);
}
这里就是添加@Service注解的属性引用。源码中标记的Add Bean reference很多,未展示完。然后我跳回到上一步的registry.registerBeanDefinition去看看。他就是告诉spring我注册了这样一个javaBean。这就是注册了一个提供者的过程。
rootBeanDefinition(ServiceBean.class);这段代码告诉我们这BeanDefinition是以ServiceBean.class为根的,所以其实就是在构造ServiceBean.
1.2 注册Provider
上一步构造了ServiceBean即一个Provider,然后进行注册。
首先ServiceBean是监听了ApplicationListener事件,当发生着个事件时,ServiceBean就会调父类的ServiceConfig的export方法进行注册。