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

dubbo源码研究之config-spring模块

阅读更多
    dubbo-config-spring模块是dubbo-config的Extension。

    Dubbo的扩展点加载从JDK标准的SPI(Service Provider Interface)扩展点发现机制加强而来。
   Dubbo改进了JDK标准的SPI的以下问题:
    JDK标准的SPI会一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源。
    如果扩展点加载失败,连扩展点的名称都拿不到了。比如:JDK标准的ScriptEngine,通过getName();获取脚本类型的名称,但如果RubyScriptEngine因为所依赖的jruby.jar不存在,导致RubyScriptEngine类加载失败,这个失败原因被吃掉了,和ruby对应不起来,当用户执行ruby脚本时,会报不支持ruby,而不是真正失败的原因。
    增加了对扩展点IoC和AOP的支持,一个扩展点可以直接setter注入其它扩展点。
   dubbo的spi约定:在扩展类的jar包内,放置扩展点配置文件:META-INF/dubbo/接口全限定名,内容为:配置名=扩展实现类全限定名,多个实现类用换行符分隔。
  
@SPI
public interface ExtensionFactory {

    /**
     * Get extension.
     * 
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);

}

   dubbo的扩展点接口ExtensionFactory ,该接口有三个实现

   dubbo的扩展实现的具体类是ExtensionLoader。
   ExtensionLoader加载扩展点时,会检查扩展点的属性(通过set方法判断),如该属性是扩展点类型,则会注入扩展点对象。因为注入时不能确定使用哪个扩展点(在使用时确定),所以注入的是一个自适应扩展(一个代理)。自适应扩展点调用时,选取一个真正的扩展点,并代理到其上完成调用。Dubbo是根据调用方法参数(上面有调用哪个扩展点的信息)来选取一个真正的扩展点。
 
 @SuppressWarnings("unchecked")
    private T createExtension(String name) {
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            injectExtension(instance);
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (wrapperClasses != null && wrapperClasses.size() > 0) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
                    type + ")  could not be instantiated: " + t.getMessage(), t);
        }
    }
    
    private T injectExtension(T instance) {
        try {
            if (objectFactory != null) {
                for (Method method : instance.getClass().getMethods()) {
                    if (method.getName().startsWith("set")
                            && method.getParameterTypes().length == 1
                            && Modifier.isPublic(method.getModifiers())) {
                        Class<?> pt = method.getParameterTypes()[0];
                        try {
                            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                method.invoke(instance, object);
                            }
                        } catch (Exception e) {
                            logger.error("fail to inject via method " + method.getName()
                                    + " of interface " + type.getName() + ": " + e.getMessage(), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return instance;
    }


   可以看出ExtensionLoader持有某一类扩展点的所有扩展,并且扩展以class为key,一个扩展类只有一个实例。
  如果扩展点使用了Adaptive则会通过字节码生成一个自适应的扩展类。
  通过createAdaptiveExtensionClassCode方法返回class的code,然后通过Compiler接口返回class对象
 
  /**
 * Compiler. (SPI, Singleton, ThreadSafe)
 * 
 * @author william.liangf
 */
@SPI("javassist")
public interface Compiler {

	/**
	 * Compile java source code.
	 * 
	 * @param code Java source code
	 * @param classLoader TODO
	 * @return Compiled class
	 */
	Class<?> compile(String code, ClassLoader classLoader);

}

   Compiler dubbo支持jdk和Javassist两种实现,特别注意一点,JdkCompiler的java版本通过硬编码指定版本为1.6。
   JdkCompiler首先通过JavaFileObject接口生成java文件,然后通过JavaCompiler接口编译成class文件,最后通过ClassLoader加载生成的class文件。
  ---------------------------分隔线-------------------------
  spring名称空间扩展
  dubbo通过扩展spring的名称空间来读取xml配置。
  dubbo.xsd是spring schma的扩展文件。作用是定义相关xml元素和名称空间。
  spring.handlers,spring.schemas是spring在解析xml的时候根据spi机制读取对象的NamespaceHandler和xsd文件位置。
  很多程序猿使用dubbo开发的时候,会发现ide工具报错,因为xml上面dubbo名称空间的链接打不开,其实这个报错可以无视的,因为spring解析的xml的时候这个网络地址其实是指向spi配置文件里面的一个java类。
  spring.handlers
 
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

   DubboNamespaceHandler则注册了相关自定义元素的解析器
 
   
/**
 * DubboNamespaceHandler
 * 
 * @author william.liangf
 * @export
 */
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));
    }

}



  • 大小: 94.4 KB
  • 大小: 40.1 KB
1
1
分享到:
评论

相关推荐

    alibaba-dubbo-dubbo-2.5.7-0-ge2d63ad.tar.gz

    《阿里巴巴Dubbo 2.5.7源码分析与应用》 阿里巴巴的Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了服务发现、服务治理、流量控制等一系列完整的服务解决方案。本压缩包"alibaba-dubbo-dubbo-2.5.7-0-ge2d...

    dubbo源码解析2

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

    dubbo+zookeeper+spring -demo.zip

    【标题】"dubbo+zookeeper+spring -demo.zip"是一个示例项目,它结合了三个重要的技术组件:Dubbo、Zookeeper和Spring。这个压缩包包含了一个完整的开发环境,用于展示如何在Java环境中使用这些技术进行分布式服务...

    dubbo.xsd文件分享

    dubbo.xsd 下载 添加 xsd 源码位置获得:dubbo-config\dubbo-config-spring\src\main\resources\META-INF\dubbo.xsd

    dubbo源码解读与实战.doc

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

    dubbo源码分析系列1

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

    dubbo-admin-2.5.4,dubbo-springmvc-zookpper集成配置详解

    在SpringMVC中使用Dubbo,首先需要在项目中引入Dubbo的相关依赖,包括`dubbo`、`spring-context-support`以及`zookeeper`客户端库。然后,配置`dubbo.properties`文件,设定Dubbo的基本属性,如应用名、注册中心地址...

    dubbo入门示例源码

    6. **配置(Config)**:Dubbo 提供了 XML、API 和 Spring 注解等多种方式进行服务的配置,包括服务的元数据、服务版本、超时时间等。 在提供的 "dubbo_provide_demo" 文件中,我们可以看到服务提供者的实现。这...

    xmljava系统源码-spring-cloud-kuang:狂神springcloud笔记+源码+config

    java系统源码 SpringCloud笔记 1、前言 1.1、回顾 回顾之前的知识 JavaSE 数据库 前端 Servlet Http Mybatis Spring SpringMVC SpringBoot Dubbo、Zookeeper、分布式基础 Maven、Git Ajax、Json ... 串一下自己会的...

    dubbo-demo:dubbo-demo学习,工程直接复制自Dubbo源码,略作简化

    - **Spring整合**:Dubbo常与Spring框架结合使用,学习如何在Spring环境中配置和管理Dubbo服务。 - **服务治理**:包括服务注册、服务发现、调用链路监控、熔断与降级策略等。 - **配置管理**:掌握Dubbo的各种配置...

    dubbo源码分析系列

    在Dubbo源码分析系列中,知秋整理了Dubbo架构设计和源码风格的详细解读,并对核心模块的职责和关系进行了深入的剖析。这对于想要了解和掌握Dubbo源码的开发者来说,是一份宝贵的资料。通过源码分析,开发者不仅能够...

    dubbo-3.1.4源码包

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

    dubbo-master.zip

    3. `dubbo-config`:Dubbo的配置模块,可能包含各种配置模板和工具,如XML配置、API配置、Spring配置等,用于定义服务元数据和服务暴露、引用的规则。 4. `dubbo-protocol`:实现Dubbo服务通信的各种协议,如Dubbo...

    incubator-dubbo-ops-master.zip

    - Spring Framework:Dubbo与Spring深度集成,利用Spring的依赖注入和AOP特性,简化服务的配置和管理。 - ZooKeeper:作为默认的服务注册中心,Zookeeper提供了可靠的分布式协调服务。 - HTTP/HTTPS:运维平台...

    dubbo2.9.0源码jar包及编译jar包

    例如,你可以研究`com.alibaba.dubbo.config.ApplicationConfig`类来了解如何配置Dubbo应用,或者深入`com.alibaba.dubbo.rpc.Invoker`接口理解远程调用的实现过程。 在Dubbo 2.9.0版本中,可能引入了一些新特性或...

    dubbo2.5.x源码

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

    dubbo源码实例

    【Dubbo源码实例解析】 Dubbo是一款由阿里巴巴开源的高性能、轻量级的服务治理框架,主要用于构建分布式服务。这个实例旨在帮助初学者快速入门,理解Dubbo的核心概念和工作原理,通过源码分析深入掌握其内部机制。 ...

    10 - 基于Maven-SpringBoot-Dubbo微服务实战

    每个依赖都对应着特定的功能模块,例如`spring-boot-starter-web`提供Web服务支持,而`dubbo-spring-boot-starter`则是Dubbo与SpringBoot整合的关键。 接着,`src`目录是源代码的根目录,通常包括`main`和`test`两...

    单点登录源码

    SpringMVC | MVC框架 | [http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc](http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#mvc) ...

    java版商城源码下载--:每天fork仓库的简介

    incubator-dubbo-spring-boot-project apache的dubbo-springboot项目 Spring-Cloud-Admin Spring Cloud微服务化开发平台,具有统一授权、认证后台管理系统,其中包含具备用户管理、资源权限管理、网关API管理等多个...

Global site tag (gtag.js) - Google Analytics