一、概述

  本篇文章是dubbo SPI源码分析的第二篇,接着第一篇继续分析dubbo SPI的内容,我们主要介绍 getDefaultExtension() 获取默认扩展点方法。

由于此方法比较简单,我们略过示例部分,直接分析源码。

二、源码分析

  获取默认扩展方法getDefaultExtension()是一个public、可对外提供调用的方法。我们知道,dubbo中扩展点接口必须要有@SPI注解修饰,@SPI注解代码如下:

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target({ElementType.TYPE})
  4. public @interface SPI {
  5.  
  6. /**
  7. * default extension name
  8. */
  9. String value() default "";
  10.  
  11. }

  注解可以修饰类和接口,同时提供 一个默认为空的value字段。

  这个value字段 就是本篇文章要介绍的默认扩展实现。

  现在我们来看getDefaultExtension()方法内部:

  1. public T getDefaultExtension() {
  2. getExtensionClasses();
  3. // cachedDefaultName为@SPI中的value
  4. if (null == cachedDefaultName || cachedDefaultName.length() == 0 || "true".equals(cachedDefaultName)) {
  5. return null;
  6. }
  7. return getExtension(cachedDefaultName);
  8. }

  第二行方法 getExtensionClasses()是加载配置文本文件,获取配置的扩展点实现类,方法执行完,会把配置文本文件的key和扩展点实现类的Class对象存储在cachedClasses 成员变量中,这个我们在第一篇已经介绍过。

  接下来就是方法的关键点,成员变量cachedDefaultName 的判断了,如果cachedDefaultName 为空或为”true“ 直接返回 null,如果cachedDefaultName 不为空,则调用getExtension(..)方法,返回扩展点实现类对象。这个方法我们在第一篇也已经介绍了。现在我们只需要分析cachedDefaultName的赋值点 就ok 了。

  成员变量cachedDefaultName 我们在第一篇有介绍到,不知道大家是否还有印象,我们现在看看变量定义:

  1. // SPI()内value,默认的接口实现
  2. private String cachedDefaultName;

  私有的字符串变量。

  变量cachedDefaultName的赋值,我们先提前介绍下,其实就是在加载配置文本文件的过程中进行的,具体的方法调用链为:

  1. getDefaultExtension() -->getExtensionClasses()-->loadExtensionClasses()

  这几个方法我们都有介绍,我们现在看看loadExtensionClasses():

  1. private Map<String, Class<?>> loadExtensionClasses() {
  2. // 获取注解 SPI的接口
  3. // type为传入的扩展接口,必须有@SPI注解
  4. final SPI defaultAnnotation = type.getAnnotation(SPI.class);
  5. // 获取默认扩展实现value,如果存在,赋值给cachedDefaultName
  6. if (defaultAnnotation != null) {
  7. String value = defaultAnnotation.value();
  8. if ((value = value.trim()).length() > 0) {
  9. // @SPI value 只能是一个,不能为逗号分割的多个
  10. // @SPI value为默认的扩展实现
  11. String[] names = NAME_SEPARATOR.split(value);
  12. if (names.length > 1) {
  13. throw new IllegalStateException("more than 1 default extension name on extension " + type.getName() + ": " + Arrays.toString(names));
  14. }
  15. if (names.length == 1)
  16. cachedDefaultName = names[0];
  17. }
  18. }
  19. // 加载三个目录配置的扩展类
  20. Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
  21. // META-INF/dubbo/internal
  22. loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
  23. // META-INF/dubbo
  24. loadDirectory(extensionClasses, DUBBO_DIRECTORY);
  25. // META-INF/services/
  26. loadDirectory(extensionClasses, SERVICES_DIRECTORY);
  27. return extensionClasses;
  28. }

  没错,对cachedDefaultName的赋值,仅此一出。

  cachedDefaultName的内容就是解析@SPI注解的value内容。此处赋值后,getDefaultExtension()方法的返回就是根据这个值进行扩展点获取并返回的。

三、总结

  获取默认扩展点的方法getDefaultExtension() 逻辑很简单,就是解析出注解@SPI的value内容,通过前一篇介绍的getExtension(..)方法进行扩展点获取。如果@SPI没有配置value或者设置的是”true“,getDefaultExtension()方法返回的就是null。

Dubbo源码分析之SPI(二)的更多相关文章

  1. dubbo源码分析2——SPI机制中的SPI实现类的读取和预处理

    SPI机制中的SPI实现类的读取和预处理是由ExtensionLoader类的loadFile方法来完成的 loadFile方法的作用是读取dubbo的某个SPI接口的spi描述文件,然后进行缓存,缓 ...

  2. Dubbo源码分析之 SPI(一)

    一.概述 dubbo SPI 在dubbo的作用是基础性的,要想分析研究dubbo的实现原理.dubbo源码,都绕不过 dubbo SPI,掌握dubbo SPI 是征服dubbo的必经之路. 本篇文 ...

  3. dubbo源码分析6——SPI机制中的AOP

    在 ExtensionLoader 类的loadFile方法中有下图的这段代码: 类如现在这个ExtensionLoader中的type 是Protocol.class,也就是SPI接口的实现类中Xx ...

  4. dubbo源码分析5——SPI机制_AdaptiveExtension的原理和作用

    private T createAdaptiveExtension() { try { return injectExtension((T) getAdaptiveExtensionClass().n ...

  5. dubbo源码分析4——SPI机制_ExtensionFactory类的作用

    ExtensionFactory的源码: @SPI public interface ExtensionFactory { /** * Get extension. * * @param type o ...

  6. dubbo源码分析3——SPI机制中的ExtensionLoader类的objectFactory属性分析

    ExtensionLoader类是整个SPI的核心类,每个SPI都会对应一个ExtensionLoader类实例,这个类的构造方法如下: private ExtensionLoader(Class&l ...

  7. dubbo源码分析1——SPI机制的概要介绍

    插件机制是Dubbo用于可插拔地扩展底层的一些实现而定制的一套机制,比如dubbo底层的RPC协议.注册中心的注册方式等等.具体的实现方式是参照了JDK的SPI思想,由于JDK的SPI的机制比较简单, ...

  8. Dubbo源码分析之SPI(三)

    一.概述 本篇介绍自适应扩展,方法getAdaptiveExtension()的实现.ExtensionLoader类本身很多功能也使用到了自适应扩展.包括ExtensionFactory扩展. 通俗 ...

  9. Dubbo 源码分析 - 服务调用过程

    注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章. 1. 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与引入.以及集群容错方面的代码.经过 ...

随机推荐

  1. nyoj 60-谁获得了最高奖学金 (逻辑判断)

    60-谁获得了最高奖学金 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:8 submit:17 题目描述:     某校的惯例是在每学期的期末考试之 ...

  2. Python之selenium自动化PART1

    本文适合有经验的测试童鞋 一.Selenium自动化测试环境搭建 1.cmd --- pip install selenium==2.53.0 (如果selenium后面不跟==,表示默认安装最新版本 ...

  3. ZeroC ICE的远程调用框架 AMI与AMD -Why?

    在Ice有两种异步使用的方式,AMI和AMD.AMI是异步方法调用,AMD是异步方法调度(分派).前者用在代理端,后者用在饲服实现端. AMI其实就是在代理端,使用Future机制进行异步调用,而不阻 ...

  4. 源码包的安装、rsync同步、inotify监测

    一.源码包的安装 1.源码包的作用:yum 使用的是rpm包,rpm包安装的不能指定安装位置 源码包可以按需选择/定制,及时修复bug ,适用于各种平台 2.大致过程:源码包——>make gc ...

  5. Orleans 3.0 为我们带来了什么

    原文:https://devblogs.microsoft.com/dotnet/orleans-3-0/ 作者:Reuben Bond,Orleans首席软件开发工程师 翻译:艾心 这是一篇来自Or ...

  6. 【2018寒假集训 Day2】【动态规划】挖地雷

    挖地雷(Mine) 在一个地图上有N 个地窖(N<=200),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径,并规定路径都是单向的,且从编号小的地窖通向编号大的地窖.某人可以从任一处 ...

  7. 和SharpDX坑爹的Variant刚正面

    和SharpDX坑爹的Variant刚正面 几个月前我写了和篇文章<.NET中生成动态验证码>文章,其实里面藏着一个大坑.运行里面的代码,会发现运行的gif图片并没有循环播放: 细心的网友 ...

  8. scrapy抓取豆瓣电影相关数据

    1. 任务分析及说明 目标网站:https://movie.douban.com/tag/#/ 抓取豆瓣电影上,中国大陆地区,相关电影数据约1000条:数据包括:电影名称.导演.主演.评分.电影类型. ...

  9. Service Mesh 是新瓶装旧酒吗?

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 李云(花名: ...

  10. 以Python为例的Async / Await的编程基础

    来源:Redislabs 作者:Loris Cro 翻译:Kevin (公众号:中间件小哥) 近年来,许多编程语言都在努力改进它们的并发原语.Go 语言有 goroutines,Ruby 有 fibe ...