`
LoveLZY
  • 浏览: 57337 次
  • 性别: Icon_minigender_1
博客专栏
Group-logo
从零编写RPC框架
浏览量:0
社区版块
存档分类
最新评论

dubbo源码研究之config模块

阅读更多
   dubbo模块说明:
   dubbo-common 公共逻辑模块,包括Util类和通用模型。
   dubbo-remoting 远程通讯模块,相当于Dubbo协议的实现,如果RPC用RMI协议则不需要使用此包。
   dubbo-rpc 远程调用模块,抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群的管理。
   dubbo-cluster 集群模块,将多个服务提供方伪装为一个提供方,包括:负载均衡, 容错,路由等,集群的地址列表可以是静态配置的,也可以是由注册中心下发。
   dubbo-registry 注册中心模块,基于注册中心下发地址的集群方式,以及对各种注册中心的抽象。
   dubbo-monitor 监控模块,统计服务调用次数,调用时间的,调用链跟踪的服务。
   dubbo-config 配置模块,是Dubbo对外的API,用户通过Config使用Dubbo,隐藏Dubbo所有细节。
   dubbo-container 容器模块,是一个Standlone的容器,以简单的Main加载Spring启动,因为服务通常不需要Tomcat/JBoss等Web容器的特性,没必要用Web容器去加载服务。
  今天开始从dubbo入口,config模块开始研究。
   config模块和Service模块是API,其他为SPI实现。
   config模块uml类图

  AbstractConfig类提供几个主要的方法       appendAnnotation,appendProperties,appendParameters,appendAttributes
  其他子类提供相关自身的属性。
  AbstractConfig类里面大量通过 反射和javabean约定获取相关值,特别注意的是toString方法注释提到的防御性容错
     catch (Throwable t) { // 防御性容错
            logger.warn(t.getMessage(), t);
            return super.toString();
        }


  防御性容错在此处使用,提升代码健壮性。
  AnnotationBean是子类里面一个比较特殊的类。因为该类是处于com.alibaba.dubbo.config.spring包下面。
该类属于config模块的spring 扩展,支持通过注解来配置dubbo。
  AnnotationBean实现了DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, ApplicationContextAware这四个接口。
   DisposableBean:资源清理接口
   BeanFactoryPostProcessor,BeanPostProcessor:作用类似,都是在bean创建之后的扩展接口。
   ApplicationContextAware:获取spring上下文接口。
   通过该类可以看出,dubbo注解实际上是spring注解的扩展,也就是说使用dubbo注解的前提是使用spring作为dubbo的容器。
   @servcie暴露dubbo服务配置的代码
  
  public Object postProcessAfterInitialization(Object bean, String beanName)
            throws BeansException {
        if (! isMatchPackage(bean)) {
            return bean;
        }
        Class<?> clazz = bean.getClass();
        if(isProxyBean(bean)){
            clazz = AopUtils.getTargetClass(bean);
        }
        Service service = clazz.getAnnotation(Service.class);
        if (service != null) {
            ServiceBean<Object> serviceConfig = new ServiceBean<Object>(service);
            if (void.class.equals(service.interfaceClass())
                    && "".equals(service.interfaceName())) {
                if (clazz.getInterfaces().length > 0) {
                    serviceConfig.setInterface(clazz.getInterfaces()[0]);
                } else {
                    throw new IllegalStateException("Failed to export remote service class " + clazz.getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces.");
                }
            }
            if (applicationContext != null) {
                serviceConfig.setApplicationContext(applicationContext);
                if (service.registry() != null && service.registry().length > 0) {
                    List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
                    for (String registryId : service.registry()) {
                        if (registryId != null && registryId.length() > 0) {
                            registryConfigs.add((RegistryConfig)applicationContext.getBean(registryId, RegistryConfig.class));
                        }
                    }
                    serviceConfig.setRegistries(registryConfigs);
                }
                if (service.provider() != null && service.provider().length() > 0) {
                    serviceConfig.setProvider((ProviderConfig)applicationContext.getBean(service.provider(),ProviderConfig.class));
                }
                if (service.monitor() != null && service.monitor().length() > 0) {
                    serviceConfig.setMonitor((MonitorConfig)applicationContext.getBean(service.monitor(), MonitorConfig.class));
                }
                if (service.application() != null && service.application().length() > 0) {
                    serviceConfig.setApplication((ApplicationConfig)applicationContext.getBean(service.application(), ApplicationConfig.class));
                }
                if (service.module() != null && service.module().length() > 0) {
                    serviceConfig.setModule((ModuleConfig)applicationContext.getBean(service.module(), ModuleConfig.class));
                }
                if (service.provider() != null && service.provider().length() > 0) {
                    serviceConfig.setProvider((ProviderConfig)applicationContext.getBean(service.provider(), ProviderConfig.class));
                } else {
                    
                }
                if (service.protocol() != null && service.protocol().length > 0) {
                    List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
                    // modified by lishen; fix dubbo's bug
                    for (String protocolId : service.protocol()) {
                        if (protocolId != null && protocolId.length() > 0) {
                            protocolConfigs.add((ProtocolConfig)applicationContext.getBean(protocolId, ProtocolConfig.class));
                        }
                    }
                    serviceConfig.setProtocols(protocolConfigs);
                }
                try {
                    serviceConfig.afterPropertiesSet();
                } catch (RuntimeException e) {
                    throw (RuntimeException) e;
                } catch (Exception e) {
                    throw new IllegalStateException(e.getMessage(), e);
                }
            }
            serviceConfig.setRef(bean);
            serviceConfigs.add(serviceConfig);
            serviceConfig.export();
        }
        return bean;
    }

   主要是先获取类上面的@servcie注解,然后new 一个对应的ServiceBean,ServiceBean继承于ServiceConfig,同时实现了spring bean的相关接口  InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware。
   最后该serviceBean保存到线程安全的容器里面去。
   @service解析是在 postProcessAfterInitialization里面
   @Reference解析是在postProcessBeforeInitialization里面,两者的时机是不一样的。
  
   String key = reference.group() + "/" + interfaceName + ":" + reference.version();
        ReferenceBean<?> referenceConfig = referenceConfigs.get(key);

  从该代码可以看出,服务接口的唯一性,由group,interfaceName 和vesion一起决定。
 
  

  • 大小: 15.3 KB
0
0
分享到:
评论

相关推荐

    dubbo源码解析2

    ### Dubbo源码解析2 #### 一、源码阅读路径 在开始深入解析Dubbo源码之前,首先需要明确的是,Dubbo虽然代码量不算庞大,但是它涉及的技术领域非常广泛,对于初学者来说,可能需要具备一定的前置知识才能更好地...

    dubbo源码解析2.0.7z

    《Dubbo源码解析2.0》是一份深入剖析阿里巴巴开源框架Dubbo核心机制的资料,专注于2.0版本的源代码分析。Dubbo作为Java领域最知名的分布式服务框架之一,其设计理念、实现原理以及在实际应用中的优化策略都是开发者...

    Dubbo 源码分析

    在源码中,`com.alibaba.dubbo.config.ApplicationConfig`和`com.alibaba.dubbo.config.ServiceConfig`类是配置服务提供者的入口。`ServiceConfig`定义了服务的元数据,包括接口名、实现类、版本、路径、参数等信息...

    dubbo-master源码

    《深入剖析Dubbo源码:探索Java微服务框架的核心机制》 Dubbo,作为阿里巴巴开源的一款高性能、轻量级的Java远程服务调用框架,它为开发者提供了丰富的服务治理功能,包括服务注册与发现、负载均衡、容错、监控等。...

    dubbo源码分析系列

    容器API模块是Dubbo内部核心模块之一,它定义了启动容器列表的Main类,包含了应用程序入口main方法。它还包括了Container接口,该接口包含了启动和停止方法的定义,以及通用的分页功能的相关类。Dubbo内置了多种容器...

    dubbo2.5.5源码

    在使用Dubbo源码进行学习时,建议按照以下步骤进行: 1. 理解整体架构:先从`dubbo`主模块的`pom.xml`文件入手,了解项目的模块划分和依赖关系。 2. 阅读核心接口:深入`dubbo-api`模块,了解`Invoker`、`...

    dubbo源码分析系列1

    《深入剖析Dubbo源码系列》 Dubbo作为国内最广泛使用的分布式服务框架,其设计思想和实现机制对于理解和构建自己的分布式服务框架至关重要。本文将基于当当网维护的dubbox版本,逐步解析Dubbo的核心模块,以帮助...

    dubbo源码解读与实战.doc

    #### 二、Dubbo源码核心模块 **2.1 模块概述** - **dubbo-common**:包含核心接口和工具类。 - **dubbo-rpc**:RPC框架的核心实现,如Protocol、Invoker、Exporter等。 - **dubbo-registry**:注册中心的实现,...

    dubbo-2.5.6源码zip

    - Config Center模块用于管理和分发配置,使得服务提供者和服务消费者的配置可以动态更新。Dubbo支持基于Zookeeper、Consul等配置中心的实现。 7. **协议与序列化** - Dubbo支持多种通信协议,如Dubbo、HTTP、RMI...

    dubbo2.5.x源码

    `dubbo-remoting`模块是Dubbo的核心之一,负责服务间的网络通信。它支持多种传输协议,如TCP、HTTP、Hessian等,并提供了`Exchange`接口用于交互模型,`Channel`接口用于表示双向通信通道。 4. **RPC机制** RPC...

    dubbo之源码

    《Dubbo源码解析》 Dubbo,作为阿里巴巴开源的一款高性能、轻量级的Java服务治理框架,已经成为了分布式服务架构的重要组成部分。深入理解Dubbo的源码,可以帮助开发者更好地运用它,解决实际开发中的问题,提升...

    dubbo-3.1.4源码包

    【标题】"dubbo-3.1.4源码包"是...通过研究这些源码,开发者可以了解到dubbo是如何实现服务治理的,以及如何在实际项目中灵活应用。同时,对于想要深入学习分布式系统和微服务架构的开发者来说,这是一个宝贵的资源。

    阿里巴巴dubbo-2.5.4源代码

    `Config`接口家族是Dubbo的配置管理模块,包括`ApplicationConfig`、`ServiceConfig`、`ReferenceConfig`等,它们对应不同的配置项,允许在运行时动态调整服务配置。 7. **服务暴露与引用** `Exporter`接口表示...

    Dubbo源代码(2.8.4)

    要编译Dubbo源码,首先需要安装Java环境和Maven,然后在项目根目录下执行`mvn clean install`命令,完成所有模块的编译。编译成功后,可以通过示例项目或自定义项目来运行和测试Dubbo服务。 5. **扩展性**: ...

    dubbo-2.6.0

    《Dubbo 2.6.0 源码解析与技术深度探讨》 Dubbo,作为阿里巴巴开源的一款高性能、轻量级的Java服务框架,深受广大开发者喜爱。...无论是对于初学者还是高级开发者,深入研究Dubbo源码都将是一次宝贵的学习经历。

    Dubbo支付系统源码.zip

    【Dubbo支付系统源码.zip】是一个包含使用Dubbo框架构建的支付系统源代码和相关数据库脚本的压缩包。...开发者可以通过研究源码,深入了解如何在实际项目中运用Dubbo和其他相关技术来构建高效、可靠的支付系统。

    Dubbo服务框架 v2.7.9-源码.zip

    这次我们关注的是其v2.7.9版本的源码,通过深入研究,可以更好地理解Dubbo的工作原理,提升我们的开发能力。 首先,我们要了解Dubbo的核心组件和设计原则。Dubbo的核心组件包括服务提供者(Provider)、服务消费者...

    dubbo 入门经验 总结

    2. 获取Dubbo源码或二进制包:可以从GitHub或Apache官网下载Dubbo的源码或者预编译的二进制包。 3. 集成到项目:如果你使用的是Maven,可以在pom.xml文件中添加Dubbo的依赖。对于非Maven项目,可以通过jar包方式...

    第四课:Dubbo调用模块详解 (2)1

    《Dubbo调用模块详解:深入理解异步调用与容错策略》 在分布式服务框架Dubbo中,调用模块扮演着至关重要的角色,它负责实现远程方法调用并确保返回结果的顺利获取。本篇文章将深入探讨Dubbo调用模块的基本组成,...

    第四课:Dubbo调用模块详解1

    Dubbo作为一款高性能的Java RPC框架,其调用模块是其核心组件之一,负责发起远程方法调用并获取返回结果。本篇将详细解析Dubbo调用模块的基本组成、非典型使用场景以及内部实现源码分析。 一、Dubbo调用模块基本...

Global site tag (gtag.js) - Google Analytics