欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Dubbo源码分析之SPI(二)

程序员文章站 2022-04-10 13:59:11
一、概述 本篇文章是dubbo SPI源码分析的第二篇,接着第一篇继续分析dubbo SPI的内容,我们主要介绍 getDefaultExtension() 获取默认扩展点方法。 由于此方法比较简单,我们略过示例部分,直接分析源码。 二、源码分析 获取默认扩展方法getDefaultExtensio ......

一、概述

  本篇文章是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-inf/dubbo/internal
22     loaddirectory(extensionclasses, dubbo_internal_directory);
23     // meta-inf/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。

Dubbo源码分析之SPI(二)