Dubbo源码学习一

简介: 首先,我们知道dubbo在以前都是基于zookeeper作为配置中心的,同时是建立在spring基础之上的。因此,就需要思考一些问题: 首先dubbo是怎样和spring集成的,也即dubbo集成在spring上需要具备什么条件?接着dubbo作为一个服务治理的微服务框架,那它的生产者和消费者与注册中心怎样进行交互的。 dubbo是基于spring的基础之上进行开发的RPC框架。需要和spring整合,必然就需要按照Spring解析默认标签和自定义标签的方式进行。而在Spring中,我们知道在Spring中是在ParseBeanDefintions(Elemen

首先,我们知道dubbo在以前都是基于zookeeper作为配置中心的,同时是建立在spring基础之上的。因此,就需要思考一些问题:

首先dubbo是怎样和spring集成的,也即dubbo集成在spring上需要具备什么条件?接着dubbo作为一个服务治理的微服务框架,那它的生产者和消费者与注册中心怎样进行交互的。

dubbo是基于spring的基础之上进行开发的RPC框架。需要和spring整合,必然就需要按照Spring解析默认标签和自定义标签的方式进行。而在Spring中,我们知道在Spring中是在ParseBeanDefintions(Element root,BeanDefintonParserDelegate delegate)方法对默认标签parseDefaultElement(ele,delegate)和自定义标签delegate.parseCustomElement(ele)进行了解析。可以看到对自定义标签的解析:

1.首先拿到命名空间namespaceuri

2.根据命名空间找到对应的NamespaceHandler

3.调用自定义的NamespaceHandler进行解析

而自定义标签的步骤:

1.首先创建一个需要进行扩展的组件

2.定义一个xsd文件描述组件内容

3.创建一个文件,实现BeanDefintionParser接口,用来解析xsd文件中的定义和组件定义

4.创建一个handler文件,扩展自NamespaceHandlerSupport,目的是将组件注册到spring容器

5..编写Spring.handlers和spring.schemas文件

也即我们可以通过这个找到dubbo的入口--dubbo-config-spring。

接着我们就可以找到解析schemas文件的BeanDefintionParser和NamespceHandlerSupport了。因此我们首先关注NamespaceHandkerSupport。

//dubbo入口publicclassDubboNamespaceHandlerextendsNamespaceHandlerSupportimplementsConfigurableSourceBeanMetadataElement {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
    }
//找到入口,解析Dubbo的相关标签的@Overridepublicvoidinit() {
//将解析好的元素的key-value信息放入到BeanDefintionMap中//registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser);//this.parsers.put(elementName, parser);// DubboBeanDefinitionParser(Class<?> beanClass, boolean required),也是key-value的map形式registerBeanDefinitionParser("application", newDubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module", newDubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry", newDubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("config-center", newDubboBeanDefinitionParser(ConfigCenterBean.class, true));
registerBeanDefinitionParser("metadata-report", newDubboBeanDefinitionParser(MetadataReportConfig.class, true));
registerBeanDefinitionParser("monitor", newDubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("metrics", newDubboBeanDefinitionParser(MetricsConfig.class, true));
registerBeanDefinitionParser("ssl", newDubboBeanDefinitionParser(SslConfig.class, true));
registerBeanDefinitionParser("provider", newDubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer", newDubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol", newDubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service", newDubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference", newDubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation", newAnnotationBeanDefinitionParser());
    }
/*** 复写NamespaceHandlerSupport的parse方法,为注解配置服务* @since 2.7.5*/@OverridepublicBeanDefinitionparse(Elementelement, ParserContextparserContext) {
BeanDefinitionRegistryregistry=parserContext.getRegistry();
//注册注解配置处理器registerAnnotationConfigProcessors(registry);
//注册上下文监听器registerApplicationListeners(registry);
//进行bena的解析BeanDefinitionbeanDefinition=super.parse(element, parserContext);
//设置资源setSource(beanDefinition);
returnbeanDefinition;
    }
/*** 将{@link ApplicationListener ApplicationListeners}注册为Spring Bean* @since 2.7.5*/privatevoidregisterApplicationListeners(BeanDefinitionRegistryregistry) {
//注册bean dubbo生命周期组件上下文监听registerBeans(registry, DubboLifecycleComponentApplicationListener.class);
//注册bean dubbo服务器上下文监听registerBeans(registry, DubboBootstrapApplicationListener.class);
    }
/***  注册注解配置处理器* @since 2.7.5*/privatevoidregisterAnnotationConfigProcessors(BeanDefinitionRegistryregistry) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(registry);
    }
}

从入口,我们可以看到相关配置信息:

ApplicationConfig、ModuleConfig、RegistryConfig、ConfigCenterBean、MetadataReportConfig、MonitorConifg、MetricsConfig、SslConfig、ProviderConfig、ConsumerConfig、ProtocolConfig、ServiceBean、ReferenceBean,还有一个注解解析:new AnnotationBeanDefinitionParser()。这里我们需要重点关注:

ServiceBean、ReferenceBean、ConfigCenterBean、new AnnotationBeanDefintionParser()

而对于相关config的配置,我们来看一个ApplicationConfig,关注两个方法,其余带config的信息都是一些实体类的信息:

//进行刷新操作,继承父类的refresh@Overridepublicvoidrefresh() {
super.refresh();
appendEnvironmentProperties();
}
//调用父类AbstractConfig#refresh方法//进行刷新操作publicvoidrefresh() {
//拿到环境变量信息Environmentenv=ApplicationModel.getEnvironment();
try {
CompositeConfigurationcompositeConfiguration=env.getPrefixedConfiguration(this);
//循环方法,将新的value设置到方法中Method[] methods=getClass().getMethods();
for (Methodmethod : methods) {
//setter方法if (MethodUtils.isSetter(method)) {
try {
Stringvalue=StringUtils.trim(compositeConfiguration.getString(extractPropertyName(getClass(), method)));
//调用isTypeMatch()方法以避免重复和不正确的更新,例如,//在ReferenceConfig中我们有两个“ setGeneric”方法。if (StringUtils.isNotEmpty(value) &&ClassUtils.isTypeMatch(method.getParameterTypes()[0], value)) {
//在具有指定参数的指定对象上,调用此方法对象表示的基础方法。//各个参数将自动展开以匹配原始形式参数,并且必要时对原始//参数和引用参数都进行方法调用转换。method.invoke(this, ClassUtils.convertPrimitive(method.getParameterTypes()[0], value));
                    }
                } catch (NoSuchMethodExceptione) {
logger.info("Failed to override the property "+method.getName() +" in "+this.getClass().getSimpleName() +", please make sure every property has getter/setter method provided.");
                }
//参数setter            } elseif (isParametersSetter(method)) {
Stringvalue=StringUtils.trim(compositeConfiguration.getString(extractPropertyName(getClass(), method)));
if (StringUtils.isNotEmpty(value)) {
Map<String, String>map=invokeGetParameters(getClass(), this);
map=map==null?newHashMap<>() : map;
map.putAll(convert(StringUtils.parseParameters(value), ""));
invokeSetParameters(getClass(), this, map);
                }
            }
        }
    } catch (Exceptione) {
//复写失败logger.error("Failed to override ", e);
    }
}
//添加环境变量配置信息privatevoidappendEnvironmentProperties() {
if (parameters==null) {
parameters=newHashMap<>();
    }
//通过扩展加载器进行获取适配器Set<InfraAdapter>adapters=ExtensionLoader.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
if (CollectionUtils.isNotEmpty(adapters)) {
Map<String, String>inputParameters=newHashMap<>();
//包含信息:应用名称和hos以及扩展参数信息inputParameters.put(APPLICATION_KEY, getName());
inputParameters.put(HOST_KEY, getHostname());
for (InfraAdapteradapter : adapters) {
//同时将SPI的扩展参数信息信息加入Map<String, String>extraParameters=adapter.getExtraAttributes(inputParameters);
if (CollectionUtils.isNotEmptyMap(extraParameters)) {
parameters.putAll(extraParameters);
            }
        }
    }
}

明天,我们关注ServiceBean、ReferenceBean、ConfigCenterBean、new AnnotationBeanDefintionParser()这四个!

目录
相关文章
|
4月前
|
缓存 Dubbo Java
趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了
趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了
|
4月前
|
Dubbo Java 应用服务中间件
从源码全面解析 dubbo 服务端服务调用的来龙去脉
从源码全面解析 dubbo 服务端服务调用的来龙去脉
|
7月前
|
Dubbo Java 应用服务中间件
由浅入深Dubbo核心源码剖析服务暴露与发现3
由浅入深Dubbo核心源码剖析服务暴露与发现3
45 0
|
7月前
|
XML Dubbo Java
由浅入深Dubbo核心源码剖析服务暴露与发现1
由浅入深Dubbo核心源码剖析服务暴露与发现1
67 0
|
7月前
|
监控 Dubbo Java
由浅入深Dubbo核心源码剖析SPI机制 2
由浅入深Dubbo核心源码剖析SPI机制
31 0
|
7月前
|
缓存 Dubbo Java
由浅入深Dubbo核心源码剖析SPI机制 1
由浅入深Dubbo核心源码剖析SPI机制
53 0
|
7月前
|
XML Dubbo 架构师
由浅入深Dubbo核心源码剖析高阶配置运用1
由浅入深Dubbo核心源码剖析高阶配置运用
50 0
|
7月前
|
Dubbo Java 应用服务中间件
由浅入深Dubbo核心源码剖析SpringBoot整合使用
由浅入深Dubbo核心源码剖析SpringBoot整合使用
87 0
|
7月前
|
监控 Dubbo Java
由浅入深Dubbo核心源码剖析环境介绍
由浅入深Dubbo核心源码剖析环境介绍
181 0
|
7月前
|
编解码 Dubbo 应用服务中间件
Alibaba开源Dubbo源码解析手册,竟引领出RPC的新潮流
前言 Apache Dubbo,一款由阿里巴巴于2011年开源的高性能Java RPC框架,自开源以来在业界产生了深远影响。有大量公司广泛使用,甚至很多公司的自研RPC框架中都能看到Dubbo的影子。Dubbo在国内服务化体系演进过程中扮演了重要角色。尽管经历了几年的沉寂,但在阿里巴巴重启对Dubbo的开源维护,Dubbo正在从微服务领域的高性能RPC框架逐步演变为一个完整的微服务生态。 对于开发者来说,深入了解Dubbo底层的架构设计和实现是一项挑战。因此,一份完整的、体系化的对Apache Dubbo进行深入原理剖析的手册就显得尤为重要。