前言
spring2.5以后,spring支持自定义schema扩展xml配置。具体的spring schema细节,本文就不多说了。这篇文章就拿provider为例,介绍dubbo是如何启动服务的。
正文
首先,再把HelloWolrd例子中的 provider.xml的源码放上来
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd "> <dubbo:application name="hello-world-app" /> <dubbo:registry protocol="zookeeper" address="10.125.195.174:2181" /> <dubbo:protocol name="dubbo" port="20880" /> <dubbo:service interface="demo.service.DemoService" ref="demoService" /> <!-- 和本地bean一样实现服务 --> <bean id="demoService" class="demo.service.DemoServiceImpl" /> </beans>
对应的自定义schema文件,就不解释了。直接在dubbo-{version}.jar 中 META-INF目录下找到对应的handler配置
spring.handlers 写道
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
可以看到,对应的handler是 DubboNamespaceHandler。对应的源码如下
public class DubboNamespaceHandler extends NamespaceHandlerSupport { static { Version.checkDuplicate(DubboNamespaceHandler.class); } public void init() { registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true)); registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true)); registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true)); registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true)); registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true)); registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true)); registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true)); registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true)); registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false)); registerBeanDefinitionParser("annotation", new DubboBeanDefinitionParser(AnnotationBean.class, true)); } }
从这里也可以看到,对应的支持的标签其实不多。所有的Parser都封装到了DubboBeanDefinitionParser中。对应的class,就是传入的beanClass。比如application的就是ApplicationConfig。module的就是ModuleConfig。经过Parser的转换,provider.xml大概可以变成如下的样子(具体的解析不多解释了)
<bean id="hello-world-app" class="com.alibaba.dubbo.config.ApplicationConfig"/> <bean id="registryConfig" class="com.alibaba.dubbo.config.RegistryConfig"> <property name="address" value="10.125.195.174:2181"/> <property name="protocol" value="zookeeper"/> </bean> <bean id="dubbo" class="com.alibaba.dubbo.config.ProtocolConfig"> <property name="port" value="20880"/> </bean> <bean id="demo.service.DemoService" class="com.alibaba.dubbo.config.spring.ServiceBean"> <property name="interface" value="demo.service.DemoService"/> <property name="ref" ref="demoService"/> </bean> <bean id="demoService" class="demo.service.DemoServiceImpl" />
分别看每一个bean的内容。由于篇幅原因,我就不把每个代码放上来了。总结一下就是
写道
ApplicationConfig,RegistryConfig,ProtocolConfig都只是普通的pojo。负责接收数据。真正的处理逻辑在ServiceBean中
看具体的代码
public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware { private static final long serialVersionUID = 213195494150089726L; private static transient ApplicationContext SPRING_CONTEXT; private transient ApplicationContext applicationContext; private transient String beanName; private transient boolean supportedApplicationListener; public ServiceBean() { super(); } public ServiceBean(Service service) { super(service); } public static ApplicationContext getSpringContext() { return SPRING_CONTEXT; } //设置对应的applicationConext public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; SpringExtensionFactory.addApplicationContext(applicationContext); if (applicationContext != null) { SPRING_CONTEXT = applicationContext; try { Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1 method.invoke(applicationContext, new Object[] {this}); supportedApplicationListener = true; } catch (Throwable t) { if (applicationContext instanceof AbstractApplicationContext) { try { Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1 if (! method.isAccessible()) { method.setAccessible(true); } method.invoke(applicationContext, new Object[] {this}); supportedApplicationListener = true; } catch (Throwable t2) { } } } } } public void setBeanName(String name) { this.beanName = name; } public void onApplicationEvent(ApplicationEvent event) { //如果容器加载完成以后当前的provider还没export,那么调用一次export方法(这个针对那种延迟export的情况) if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) { if (isDelay() && ! isExported() && ! isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } export(); } } } //是否延迟export private boolean isDelay() { Integer delay = getDelay(); ProviderConfig provider = getProvider(); if (delay == null && provider != null) { delay = provider.getDelay(); } return supportedApplicationListener && (delay == null || delay.intValue() == -1); } @SuppressWarnings({ "unchecked", "deprecation" }) public void afterPropertiesSet() throws Exception { //这里的Provider其实就是ProviderConfig对象。如果provider为空,表示spring在创建 当前bean的时候还没有初始化ProtocolConfig bean。这里就是做一个前后顺序保证 if (getProvider() == null) { Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false); if (providerConfigMap != null && providerConfigMap.size() > 0) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if ((protocolConfigMap == null || protocolConfigMap.size() == 0) && providerConfigMap.size() > 1) { // 兼容旧版本 List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>(); for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() != null && config.isDefault().booleanValue()) { providerConfigs.add(config); } } if (providerConfigs.size() > 0) { setProviders(providerConfigs); } } else { ProviderConfig providerConfig = null; for (ProviderConfig config : providerConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (providerConfig != null) { throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config); } providerConfig = config; } } if (providerConfig != null) { setProvider(providerConfig); } } } } //这里和上面同样,手动创建ApplicationConfig bean if (getApplication() == null && (getProvider() == null || getProvider().getApplication() == null)) { Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false); if (applicationConfigMap != null && applicationConfigMap.size() > 0) { ApplicationConfig applicationConfig = null; for (ApplicationConfig config : applicationConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (applicationConfig != null) { throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config); } applicationConfig = config; } } if (applicationConfig != null) { setApplication(applicationConfig); } } } //如果没有创建module,则手动创建 module。 在HelloWorld例子中,没有用到module。 if (getModule() == null && (getProvider() == null || getProvider().getModule() == null)) { Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false); if (moduleConfigMap != null && moduleConfigMap.size() > 0) { ModuleConfig moduleConfig = null; for (ModuleConfig config : moduleConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (moduleConfig != null) { throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config); } moduleConfig = config; } } if (moduleConfig != null) { setModule(moduleConfig); } } } //初始化registiry if ((getRegistries() == null || getRegistries().size() == 0) && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0) && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) { Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false); if (registryConfigMap != null && registryConfigMap.size() > 0) { List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); for (RegistryConfig config : registryConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { registryConfigs.add(config); } } if (registryConfigs != null && registryConfigs.size() > 0) { super.setRegistries(registryConfigs); } } } //初始化monitor (HelloWorld例子中没有用到) if (getMonitor() == null && (getProvider() == null || getProvider().getMonitor() == null) && (getApplication() == null || getApplication().getMonitor() == null)) { Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false); if (monitorConfigMap != null && monitorConfigMap.size() > 0) { MonitorConfig monitorConfig = null; for (MonitorConfig config : monitorConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { if (monitorConfig != null) { throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config); } monitorConfig = config; } } if (monitorConfig != null) { setMonitor(monitorConfig); } } } //初始化protocol if ((getProtocols() == null || getProtocols().size() == 0) && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) { Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false); if (protocolConfigMap != null && protocolConfigMap.size() > 0) { List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>(); for (ProtocolConfig config : protocolConfigMap.values()) { if (config.isDefault() == null || config.isDefault().booleanValue()) { protocolConfigs.add(config); } } if (protocolConfigs != null && protocolConfigs.size() > 0) { super.setProtocols(protocolConfigs); } } } //设置服务名称。 if (getPath() == null || getPath().length() == 0) { if (beanName != null && beanName.length() > 0 && getInterface() != null && getInterface().length() > 0 && beanName.startsWith(getInterface())) { setPath(beanName); } } //调用export if (! isDelay()) { export(); } } //调用unexport public void destroy() throws Exception { unexport(); } }
代码里面已经加了一些注释。虽然很长,逻辑还是很简单的。其中用到了spring的很多特性。非常值得我们学习。
很明显,下一篇就要介绍 核心的 export 和unexport方法了。
相关推荐
dubbo源码dubbo-dubbo-2.7.3.rardubbo源码dubbo-dubbo-2.7.3.rardubbo源码dubbo-dubbo-2.7.3.rardubbo源码dubbo-dubbo-2.7.3.rardubbo源码dubbo-dubbo-2.7.3.rardubbo源码dubbo-dubbo-2.7.3.rardubbo源码dubbo-dubbo...
dobbo源码dubbo-dubbo-2.7.3.rardobbo源码dubbo-dubbo-2.7.3.rardobbo源码dubbo-dubbo-2.7.3.rardobbo源码dubbo-dubbo-2.7.3.rardobbo源码dubbo-dubbo-2.7.3.rardobbo源码dubbo-dubbo-2.7.3.rardobbo源码dubbo-dubbo...
在实际部署中,`dubbo-monitor-simple-2.5.4-SNAPSHOT-assembly.tar.gz`包含了Dubbo监控的组件,解压后可以配置启动,使得消费者和服务提供者能将调用信息上报到监控中心。`dubbo-demo-consumer-2.5.4-SNAPSHOT-...
2. 配置启动:进入`dubbo-monitor-simple-2.5.8/bin`目录,执行启动脚本(如`start.sh`或`start.bat`),启动监控服务。默认监听8080端口。 3. 配置Dubbo服务:在提供者和服务消费者端的Dubbo配置中,需要添加`...
总之,`dubbo-admin-2.5.4.war`为开发者提供了一个强大的服务治理工具,通过它,我们可以对Dubbo服务进行精细化管理,提升系统的稳定性和效率。熟练掌握其使用,无疑会极大地提升开发和运维的效率。
本人实际测试过,这两个包可用。...2.修改dubbo-monitor中的conf目录中的dubbo.properties dubbo.registry.address 与 dubbo-admin中的配置一样 3.到dubbo-monitor中的bin目录下运行 start.sh脚本 ok
标签 "springboot-2" 和 "dubbo-2.6.x" 明确了项目所使用的具体技术版本。Spring Boot 2.0.x 引入了许多改进和新特性,包括对 Spring Framework 5 和 Java 9 的支持,以及更好的性能和稳定性。而 Dubbo 2.6.x 版本则...
jmeter的dubbo插件,jmeter-plugins-dubbo-2.7.8-jar-with-dependencies.jar,适用于JMeter5.4.1版本,将解压后的文件jmeter-plugins-dubbo-2.7.8-jar-with-dependencies放在Jmeter安装目录下的\lib\ext文件夹中,...
dubbo-admin-2.5.4提供支持JDK1.7及JDK1.8的War包 Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度地松耦合)。从服务模型的角度来看...
- 启动监控服务:部署`dubbo-monitor-simple`应用,提供监控接口和服务。 - 服务提供者注册:服务提供者启动时会向监控中心注册自身信息,包括服务名、版本、地址等。 - 服务消费者调用:服务消费者在调用服务时,...
本文将深入探讨“jmeter-plugins-dubbo-2.7.1-jar-with-dependencies”这一系统压测工具包,它专门针对基于Java的Dubbo服务进行性能测试。了解并熟练掌握这一工具,能帮助我们更好地优化服务性能,提升系统的稳定性...
dubbo官方自带了dubbo-admin及dubbo-simple/dubbo-monitor-simple二个子项目用于服务治理及服务监控。 dubbo-monitor-simple是Alibaba的开源项目,用于监控在dubbo框架下接口暴露,注册情况,也可以看接口的调用...
本文将深入探讨"jmeter-plugins-dubbo-2.7.1-jar-with-dependencies (1)"这个压缩包中的关键知识点。 1. **JMeter Plugins for Dubbo** JMeter Plugins for Dubbo 是一个扩展了JMeter功能的插件,专门用于测试基于...
首先,我们关注的是“dubbo-monitor-simple”这个组件,它是Dubbo监控体系的一部分,主要负责收集、展示服务的运行数据,如调用次数、成功率、响应时间等,帮助开发者实时了解服务状态,及时发现并解决问题。...
Dubbo是阿里巴巴开源的一款高性能、轻量级的服务治理框架,而`dubbo-admin-2.5.4`则是Dubbo框架中的一个重要组件,它是一个用于监控和服务管理的Web应用。这个war包的提供,使得开发者和运维人员能够更便捷地管理和...
【描述】表明这是一个结合了dubbox、springBoot和dubbo-monitor-web的项目源码,适合开发者进行学习和实践,以了解如何将这三个组件集成到一起,实现服务的监控和管理。 【标签】“dubbo monitor”进一步强调了本...