一, 概述
本篇文章是 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 的赋值, 我们先提前介绍下, 其实就是在加载配置文本文件的过程中进行的, 具体的方法调用链为:
1 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.
来源: https://www.cnblogs.com/yxfree/p/12053225.html