一、概述

  本篇文章是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. Linux运维利器之ClusterShell

    一.简介 实验室机房有大概百台的服务器需要管理,加上需要搭建Hadoop以及Spark集群等,因此,一个轻量级的集群管理软件就显得非常有必要了.经过一段时间的了解以及尝试,最终选择了clustersh ...

  2. Arduino驱动ILI9341彩屏(一)——颜色问题

    最近在淘宝的店铺上淘到了一块ILI9341的彩色液晶屏,打算研究一下如何使用. 淘宝店铺购买屏幕之后有附源代码可供下载,代码质量惨不忍睹,各种缩进不规范就不说了,先拿来试一下吧. 这是淘宝店铺代码的核 ...

  3. Ubuntu 16.04安装ROS Kinetic详细教程 | Tutorial to Install and Configure ROS Kinetic on Ubuntu 16.04

    本文首发于个人博客https://kezunlin.me/post/e2780b93/,欢迎阅读! Tutorial to Install and Configure ROS Kinetic on U ...

  4. linux 正确的关机流程

    查看系统的使用状态 1.使用who命令查看在线用户. 2.使用netstat -a或ss -tnl查看网络状态: 3.使用ps -aux 查看后台运行的程序. 通过上述操作可以了解系统目前使用状态,从 ...

  5. PostgreSQL的使用向导

    目录 数据库 创建数据库 进入数据库 查看版本 查看当前时间日期 简单的select 获得帮助命令 退出psql客户端 创建表 weather和cities表的创建 删除表 插入数据 数据库导出成cs ...

  6. .Net Core 3.0 使用 Serilog 把日志记录到 SqlServer

    Serilog简介 Serilog是.net中的诊断日志库,可以在所有的.net平台上面运行.Serilog支持结构化日志记录,对复杂.分布式.异步应用程序的支持非常出色.Serilog可以通过插件的 ...

  7. LESSON 3- Discrete Memory-less Sources

    1.     Entropy H[X] - bounds on Lmin 2.      Huffman’s algorithm for optimal source code

  8. PHP安装sodium加密扩展

    1.为什么会用到sodium加密扩展? 最近在做微信服务商相关的开发,主要用的的接口为微信小微商户进件接口.在请求相关接口中,需要对一些敏感字段进行加密,加密过程见https://pay.weixin ...

  9. 【Android - 问题解决】之ScrollView嵌套ListView时总是自动滑动到ListView顶部的问题

    最近做了一个项目,里面有一个ScrollView嵌套ListView的布局. 做出来之后发现,进入这个界面之后,总是自动滑动到ListView的顶部,而ScrollView中位于ListView上面的 ...

  10. 【Android - 自定义View】之自定义View实现“刮刮卡”效果

    首先来介绍一下这个自定义View: (1)这个自定义View的名字叫做 GuaguakaView ,继承自View类: (2)这个View实现了很多电商项目中的“刮刮卡”的效果,即用户可以刮开覆盖层, ...