Dubbo源码分析之SPI(二)
一、概述
本篇文章是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。