Dubbo源码分析之SPI(二)
一、概述
本篇文章是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(二)的更多相关文章
- dubbo源码分析2——SPI机制中的SPI实现类的读取和预处理
SPI机制中的SPI实现类的读取和预处理是由ExtensionLoader类的loadFile方法来完成的 loadFile方法的作用是读取dubbo的某个SPI接口的spi描述文件,然后进行缓存,缓 ...
- Dubbo源码分析之 SPI(一)
一.概述 dubbo SPI 在dubbo的作用是基础性的,要想分析研究dubbo的实现原理.dubbo源码,都绕不过 dubbo SPI,掌握dubbo SPI 是征服dubbo的必经之路. 本篇文 ...
- dubbo源码分析6——SPI机制中的AOP
在 ExtensionLoader 类的loadFile方法中有下图的这段代码: 类如现在这个ExtensionLoader中的type 是Protocol.class,也就是SPI接口的实现类中Xx ...
- dubbo源码分析5——SPI机制_AdaptiveExtension的原理和作用
private T createAdaptiveExtension() { try { return injectExtension((T) getAdaptiveExtensionClass().n ...
- dubbo源码分析4——SPI机制_ExtensionFactory类的作用
ExtensionFactory的源码: @SPI public interface ExtensionFactory { /** * Get extension. * * @param type o ...
- dubbo源码分析3——SPI机制中的ExtensionLoader类的objectFactory属性分析
ExtensionLoader类是整个SPI的核心类,每个SPI都会对应一个ExtensionLoader类实例,这个类的构造方法如下: private ExtensionLoader(Class&l ...
- dubbo源码分析1——SPI机制的概要介绍
插件机制是Dubbo用于可插拔地扩展底层的一些实现而定制的一套机制,比如dubbo底层的RPC协议.注册中心的注册方式等等.具体的实现方式是参照了JDK的SPI思想,由于JDK的SPI的机制比较简单, ...
- Dubbo源码分析之SPI(三)
一.概述 本篇介绍自适应扩展,方法getAdaptiveExtension()的实现.ExtensionLoader类本身很多功能也使用到了自适应扩展.包括ExtensionFactory扩展. 通俗 ...
- Dubbo 源码分析 - 服务调用过程
注: 本系列文章已捐赠给 Dubbo 社区,你也可以在 Dubbo 官方文档中阅读本系列文章. 1. 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与引入.以及集群容错方面的代码.经过 ...
随机推荐
- nyoj 60-谁获得了最高奖学金 (逻辑判断)
60-谁获得了最高奖学金 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:8 submit:17 题目描述: 某校的惯例是在每学期的期末考试之 ...
- Python之selenium自动化PART1
本文适合有经验的测试童鞋 一.Selenium自动化测试环境搭建 1.cmd --- pip install selenium==2.53.0 (如果selenium后面不跟==,表示默认安装最新版本 ...
- ZeroC ICE的远程调用框架 AMI与AMD -Why?
在Ice有两种异步使用的方式,AMI和AMD.AMI是异步方法调用,AMD是异步方法调度(分派).前者用在代理端,后者用在饲服实现端. AMI其实就是在代理端,使用Future机制进行异步调用,而不阻 ...
- 源码包的安装、rsync同步、inotify监测
一.源码包的安装 1.源码包的作用:yum 使用的是rpm包,rpm包安装的不能指定安装位置 源码包可以按需选择/定制,及时修复bug ,适用于各种平台 2.大致过程:源码包——>make gc ...
- Orleans 3.0 为我们带来了什么
原文:https://devblogs.microsoft.com/dotnet/orleans-3-0/ 作者:Reuben Bond,Orleans首席软件开发工程师 翻译:艾心 这是一篇来自Or ...
- 【2018寒假集训 Day2】【动态规划】挖地雷
挖地雷(Mine) 在一个地图上有N 个地窖(N<=200),每个地窖中埋有一定数量的地雷.同时,给出地窖之间的连接路径,并规定路径都是单向的,且从编号小的地窖通向编号大的地窖.某人可以从任一处 ...
- 和SharpDX坑爹的Variant刚正面
和SharpDX坑爹的Variant刚正面 几个月前我写了和篇文章<.NET中生成动态验证码>文章,其实里面藏着一个大坑.运行里面的代码,会发现运行的gif图片并没有循环播放: 细心的网友 ...
- scrapy抓取豆瓣电影相关数据
1. 任务分析及说明 目标网站:https://movie.douban.com/tag/#/ 抓取豆瓣电影上,中国大陆地区,相关电影数据约1000条:数据包括:电影名称.导演.主演.评分.电影类型. ...
- Service Mesh 是新瓶装旧酒吗?
点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 李云(花名: ...
- 以Python为例的Async / Await的编程基础
来源:Redislabs 作者:Loris Cro 翻译:Kevin (公众号:中间件小哥) 近年来,许多编程语言都在努力改进它们的并发原语.Go 语言有 goroutines,Ruby 有 fibe ...