一、概述

  本篇文章是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. 关于 “'sqlite3' 不是内部或外部命令.....”问题

    学习django 按书上的  执行 manage.py dbshell 时, 报“'sqlite3' 不是内部或外部命令,也不是可运行的程序 或批处理文件.” 也就是指,环境变量中没有“sqlite3 ...

  2. error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'

    用Python打开图像始终提示错误 error: OpenCV(4.1.1) C:\projects\opencv-python\opencv\modules\highgui\src\window.c ...

  3. 关于log4j

    搭建完maven+SpringMVC以后,我们还需要添加日志功能,方便记录应用在应用中产生的日志信息. 1.添加依赖包:依赖中除了对slf4j依赖外还有对邮件插件的依赖.当遇到报错的时候可以发送邮件到 ...

  4. static declaration follows non-static declaration

    前段时间工作中要为android编译跨平台的第三方库,遇到了arc4random有关函数的“static declaration follows non-static declaration”问题,那 ...

  5. 在 Vue中使用layui日历控件,标注重要日子

    因为在vue文件中通过import加载,不知道为什么打包后会找不到js, 所以通过这种方法引入 在index.html中引入 文件目录 需要放在static目录下 <input type=&qu ...

  6. aws msk

    1. 建立3个私网子网 2. 建立msk

  7. Flex容器拖动(Bordercontainer为例)

    Bordercontainer的拖放到任意位置. mxml: 为Bordercontainer添加鼠标按下和弹起事件 <s:BorderContainer id="bdShow&quo ...

  8. 安卓Android碎片fragment实现静态加载

    静态加载好后的界面如下,两个碎片分别位于一个活动的左边和右边: 左边和右边分别为一个碎片,这两个碎片正好将一整个活动布满.一个活动当中可以拥有多个碎片,碎片的含义就是可以在同一个UI界面下,将这个界面 ...

  9. vue中插槽的使用场景

    效果图:

  10. PV、UV、IP、TPS、QPS、RPS等网络度量术语

    PV:(访问量)即Page View --页面浏览量或单击量.用户每一次对网站中的任何页面进行访问后,被记录为一次PV,用户对同一页面的多次刷新,访问量将进行累计: UV:(独立访客)即Unique ...