Dubbo源码学习一

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 首先,我们知道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()这四个!

目录
相关文章
|
7月前
|
Dubbo Java 应用服务中间件
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
|
7月前
|
缓存 Dubbo Java
趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了
趁同事上厕所的时间,看完了 Dubbo SPI 的源码,瞬间觉得 JDK SPI 不香了
|
7月前
|
Dubbo Java 应用服务中间件
从源码全面解析 dubbo 服务端服务调用的来龙去脉
从源码全面解析 dubbo 服务端服务调用的来龙去脉
|
Dubbo Java 应用服务中间件
由浅入深Dubbo核心源码剖析服务暴露与发现3
由浅入深Dubbo核心源码剖析服务暴露与发现3
72 0
|
XML Dubbo Java
由浅入深Dubbo核心源码剖析服务暴露与发现1
由浅入深Dubbo核心源码剖析服务暴露与发现1
96 0
|
监控 Dubbo Java
由浅入深Dubbo核心源码剖析SPI机制 2
由浅入深Dubbo核心源码剖析SPI机制
65 0
|
7月前
|
缓存 Dubbo Java
Dubbo 第三节_ Dubbo的可扩展机制SPI源码解析
Dubbo会对DubboProtocol对象进⾏依赖注⼊(也就是⾃动给属性赋值,属性的类型为⼀个接⼝,记为A接⼝),这个时候,对于Dubbo来说它并不知道该给这个属性赋什么值,换句话说,Dubbo并不知道在进⾏依赖注⼊时该找⼀个什么的的扩展点对象给这个属性,这时就会预先赋值⼀个A接⼝的⾃适应扩展点实例,也就是A接⼝的⼀个代理对象。在调⽤getExtension去获取⼀个扩展点实例后,会对实例进⾏缓存,下次再获取同样名字的扩展点实例时就会从缓存中拿了。Protocol是⼀个接。但是,不是只要在⽅法上加了。
|
2月前
|
存储 负载均衡 监控
dubbo学习一:zookeeper与dubbo的关系,下载安装启动zookeeper(解决启动中报错)
这篇文章是关于Apache Dubbo框架与Zookeeper的关系,以及如何下载、安装和启动Zookeeper的教程,包括解决启动过程中可能遇到的报错问题。
102 3
dubbo学习一:zookeeper与dubbo的关系,下载安装启动zookeeper(解决启动中报错)
|
2月前
|
Dubbo Java 应用服务中间件
Dubbo学习圣经:从入门到精通 Dubbo3.0 + SpringCloud Alibaba 微服务基础框架
尼恩团队的15大技术圣经,旨在帮助开发者系统化、体系化地掌握核心技术,提升技术实力,从而在面试和工作中脱颖而出。本文介绍了如何使用Dubbo3.0与Spring Cloud Gateway进行整合,解决传统Dubbo架构缺乏HTTP入口的问题,实现高性能的微服务网关。
|
2月前
|
监控 Dubbo Java
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。
这篇文章详细介绍了如何将Spring Boot与Dubbo和Zookeeper整合,并通过Dubbo管理界面监控服务注册情况。
176 0
dubbo学习三:springboot整合dubbo+zookeeper,并使用dubbo管理界面监控服务是否注册到zookeeper上。