一、概述

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

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

二、源码分析

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

 @Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SPI { /**
* default extension name
*/
String value() default ""; }

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

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

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

 public T getDefaultExtension() {
getExtensionClasses();
// cachedDefaultName为@SPI中的value
if (null == cachedDefaultName || cachedDefaultName.length() == 0 || "true".equals(cachedDefaultName)) {
return null;
}
return getExtension(cachedDefaultName);
}

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

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

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

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

  私有的字符串变量。

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

 getDefaultExtension() -->getExtensionClasses()-->loadExtensionClasses()

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

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

  没错,对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 20-吝啬的国度 (DFS)

    20-吝啬的国度 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:12 submit:43 题目描述: 在一个吝啬的国度里有N个城市,这N个城市间只有 ...

  2. ansible-template

    template简介 template功能: 根据模板文件动态生成对应的配置文件 template文件必须存放于templates目录下,且命名为 .j2 结尾 ansible的template模板使 ...

  3. ASP.NET Core +Highchart+ajax绘制动态柱状图

    一.项目介绍利用前端Highchart,以及ajax向后台获取数据,绘制动态柱状图.hightchart其他实例可查看官网文档.[Highchart](https://www.highcharts.c ...

  4. 闲来无事写了一套 Jenkins 主题样式:刀锋

    背景 Jenkins 的前端 CSS 样式坚挺了这么多年已经觉得腻的不行了,于是想换个风格缓解一下视觉疲劳,便有了这个项目.由于本人不是前端,所以很多只是随便改改,有些复杂的需求也实现不了,但是总的来 ...

  5. day 24 组合的补充

    一.组合的补充: 1.类或对象可以做字典的key 2.对象中到底有什么? # class Foo(object): # # def __init__(self,age): # self.age = a ...

  6. 2019/12/1 智能硬件实验室(ROS方向)

    浅谈安装ubuntu与ros感想 ubuntu 以前看电脑软件安装管家上的教程尝试在另一台电脑上安装ubuntu(虚拟机上),但是后面遇到了无法解决的问题,放弃了.这次因为选的ros方向,所以昨天在学 ...

  7. Kotlin协程通信机制: Channel

    Coroutines Channels Java中的多线程通信, 总会涉及到共享状态(shared mutable state)的读写, 有同步, 死锁等问题要处理. 协程中的Channel用于协程间 ...

  8. Linux01机和Linux02机的切换 和秘钥的配置

    先试一下 01机和02机是否可以切换成功 使用 ssh root@ip地址 输入密码 ifconfig查看ip是否正确 切换回01机 01机配置的秘钥 查看隐形文件 01机配置秘钥 输入  ssh-c ...

  9. Sql 修改表结构

    添加字段 alter table 表名 add 字段名 nvarchar(100) not null 修改字段 alter table 表名 alter column 字段名 int not null ...

  10. flask实现验证码并验证

    效果图: 点击图片.刷新页面.输入错误点击登录时都刷新验证码 实现步骤: 第一步:先定义获取验证码的接口 verificationCode.py #验证码 @api.route('/imgCode') ...