Dubbo源代码实现一:切入Spring
来源:互联网 发布:php从入门到精通下载 编辑:程序博客网 时间:2024/06/07 16:05
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?不得而知。
- Dubbo源代码实现一:切入Spring
- spring实现dubbo服务
- 切入效果实现
- Dubbo源代码实现三:注册中心Registry
- Spring事务管理-aop切入配置
- [置顶] spring aop 切入aciton
- dubbo + zookeeper + spring 分布式系统(一)
- (一)dubbo+redis注册中心+spring
- Spring中APO切入同类下的其他方法实现事务控制
- spring源代码学习(一)
- Dubbo源代码实现五:RPC中的服务消费方实现
- dubbo学习(一)-dubbo基于SPI思想的实现
- dubbo学习(一)-dubbo基于SPI思想的实现
- Dubbo/Dubbox的dubbo协议实现(一)-服务端启动
- dubbo和zookeeper,spring结合实现服务
- Spring Mvc 集成dubbo实现分布式
- dubbo系列(一)——dubbo简介和dubbo+spring+zookeeper配置整合
- Spring源代码解析(一)Spring中的事务处理
- Spring MVC 创建自定义转换器
- JVM常用调优参数
- 如何根据历史数据监控当前数据是否异常
- Spring如何扫描class和配置文件
- HttpClient入门示例
- Dubbo源代码实现一:切入Spring
- Flume快速入门(五):File Channel之重播(replay)
- 常用限流方案的设计和实现
- RocketMQ初探一:NameServer的作用
- Flume快速入门(一):背景简介
- 基础算法(排序)
- JNI综合实验一:LED点亮+IO电平读取
- Flume快速入门(二):设计从简
- Flume快速入门(三):File Channel之写Event