Dubbo是阿里开源的一个高性能服务框架,提供了服务注册、RPC服务调用、调用均衡、服务监控和服务failover等功能。如果你还未使用过Dubbo框架,请先参考dubbo提供的官方文档,比如:http://www.oschina.net/p/dubbo?fromerr=iVZFqWON。
Dubbo框架中有两个重要角色:(服务)提供者和(服务)消费者,这里为了简单起见,将包含了dubbo提供者或消费者功能的应用模块通称为dubbo客户端。
带着问题看源代码,才能有收获。
进入正题,现在大多数java应用都离不开Spring,所以其他java解决方案,或多或少都会支持在Spring中使用,dubbo也不例外。在我记忆中,凡是想在Spring容器中发挥作用的框架,无非都是提供对应的Spring Bean来注入到Spring容器中,dubbo也一样。在源代码的dubbo-container-spring模块中,唯一的类SpringContainer说明了这一点,它的start()方法直接通过ClassPathXmlApplicationContext来启动Spring容器。有人立马会问,SpringContainer的start()方法由谁调用?答案就是com.alibaba.dubbo.container.Main,它是dubbo的入口,Main类中的main方法将依次调用dubbo内置的Container的start()方法。如果没有配置Spring xml文件的路径,dubbo将会默认采用classpath*:META-INF/spring/*.xml。
那么问题来了,Spring是如何识别dubbo的那些自定义标签的?Spring为了支持用户自定义类加载到Spring容器,提供了org.springframework.beans.factory.xml.NamespaceHandler接口和org.springframework.beans.factory.xml.NamespaceHandlerSupport抽象类,NamespaceHandler#init方法会在对象的构造函数调用之后、属性初始化之前被DefaultNamespaceHandlerResolver调用。dubbo的DubboNamespaceHandler类正是继承了NamespaceHandlerSupport,其代码实现如下:
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)); } }
registerBeanDefinitionParser方法有父抽象了类NamespaceHandlerSupport的默认实现,第一个参数是elementName,即元素名称,即告诉Spring你要解析哪个标签,第二个参数是BeanDefinitionParser的实现类,BeanDefinitionParser是Spring用来将xml元素转换成BeanDefinition对象的接口。dubbo的DubboBeanDefinitionParser类就实现了这个接口,负责将标签转换成bean定义对象BeanDefinition。dubbo给其返回的BeanDefinition设置了下列属性:
beanDefinition.setBeanClass(beanClass);
beanDefinition.setLazyInit(false);
beanDefinition.getPropertyValues().addPropertyValue("id", id);
如果是dubbo:protocol标签,dubboh还会检查所有已经包含protocol属性的BeanDefinition且protocol属性对应的值是ProtocolConfig对象的bean,将其属性的protocol值设置成当前的bean引用:
definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));
如果是dubbo服务提供者的dubbo:service标签,则还会设置ref属性为对应接口class的实现类bean:
beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
有没有人想过,当使用dubbo服务提供者的dubbo:service标签时,如果我既不设置id,也不设置name,则dubbo给它的ServiceBean在Spring容器中定义的ID是什么? 答案就是:
if (generatedBeanName == null || generatedBeanName.length() == 0) {
generatedBeanName = beanClass.getName();
}
id = generatedBeanName;
int counter = 2;
while(parserContext.getRegistry().containsBeanDefinition(id)) {
id = generatedBeanName + (counter ++);
}
有人就会问,Spring怎么知道你自定义了NamespaceHandlerSupport的实现类?Spring容器会默认加载classpath/META-INF下的spring.handlers和spring.schemas文件,来加载名空间处理器和xsd,所以dubbo-config-spring包下的META-INF目录下就有这两个文件。
最后,DubboNamespaceHandler类中的静态代码块去classpath下检查是否有其他的同名class,否则会打错误日志,这个是为什么呢?防止不同的类加载器重复加载DubboNamespaceHandler?不得而知。
相关推荐
spring_dubbo spring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_dubbospring_...
此框架为Spring4.1.6+mybatis3.2.8+dubbo2.5.3的框架源码以及依赖的包
dubbo示例代码dubbo-sample
如果使用dubbo遇到错误:com.alibaba.dubbo.remoting.RemotingException: Fail to decode request due to: RpcInvocation 请下载这个jar,替换掉你项目中的那个jar,应该可以解决。
Dubbo的源代码打包,2.8.4开发发布版,及与Maven构建,本人亲测,可以编译通过。
Dubbo的源代码打包,2.5.4开发发布版,及与Maven构建,本人亲测,可以编译通过。
dubbo分布式服务框架,方便大家对分布式服务的学习,方便对dubbo的扩展
1.SpringBoot聚合工程整合Dubbo,实现服务提供者与服务消费者的数据调用, 2.该项目提高了自己对Spring Boot整合Dubbo的理解,并深刻的认识到了服务者与消费者之间的调用及流程 4. Dubbo配置全部采用yml文件配置,...
用于测试spring dubbo功能,提供对spring boot的支持
targetNamespace="http://code.alibabatech.com/schema/dubbo"> <xsd:import namespace="http://www.w3.org/XML/1998/namespace"/> <xsd:import namespace="http://www.springframework.org/schema/beans"/> ...
传统工程改造成Dubbo工程...dubbodemo-service : 只做逻辑实现,也就是dubbo中的生产者 dubbodemo-web : 负责页面跳转及渲染,也就是dubbo中的消费者 讲解 : http://blog.csdn.net/shangmingtao/article/details/78017510
该文档分析了 Dubbo 框架中 RPC 调用的整个流程,并基于源代码按照执行 时序进行说明,源码版本为2.5.4开发版。 涉及的关键点包括:Invocation、Invoker、Directory、路由、负载均衡、集群容错、过滤器以及监控模块...
apache dubbo官网最简单的小例子,只是按照说明弄了下。
本人实际测试过,这两个包可用。...2.修改dubbo-monitor中的conf目录中的dubbo.properties dubbo.registry.address 与 dubbo-admin中的配置一样 3.到dubbo-monitor中的bin目录下运行 start.sh脚本 ok
这是一个学习zookeeper+dubbo+spring的代码例子,一个maven工程
本项目只适合dubbo入门学习者,高手请不要浪费金钱; 本项目技术栈 springboot, dubbo ,无 zookeeper 本项目旨在提供最单纯的 dubbo 服务提供者 和消费者的点对点直连,而摒弃任何多余技术对dubbo直连的理解
SSM+dubbo项目源代码
dubbo入门完整实例,从发布到调用,代码完全实现。
使用spring配置文件配置dubbo服务,ioc注入。不是其他入门实例的api启动。 每一步可能犯的错误都在下面的地址里有详细描述 详细介绍参见blog http://blog.csdn.net/fangxiaoji/article/details/41845955
一个完整的dubbo服务端和消费端实例,集成spring实现双向通信!