Dubbo源码分析之SPI(二)

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

Dubbo源码分析之SPI(二)

yxfree   2019-12-17 我要评论

一、概述

  本篇文章是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-INFhttps://img.qb5200.com/download-x/dubbo/internal
22     loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
23     // META-INFhttps://img.qb5200.com/download-x/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。

 

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们