dubbo SPI 实现原理

dubbo SPI 实现原理

a).定义一个接口
b).实现一个接口
c).在 MATE-INF/dobbo 下创建以接口全限定名的文件名
d).文件内容为 key=实现类全限定名 例如: impl=chenyi.dubbo.test.dubbo.PrintInfoDubboServiceImpl
e).接口添加注解SPI(“impl”)SPI:是dubbo包下的。 impl是配置文件中的key
f).通过dubbo的方式获取对应扩展类: ExtensionLoader.getExtensionLoader(PrintInfoDubboService.class)
.getDefaultExtension();

接下来就通过获取对应扩展类的代码看看底层是怎么实现的:


        //获取扩展加载类
        public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
            if (type == null) {
                throw new IllegalArgumentException("Extension type == null");
            } else if (!type.isInterface()) {
                throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
                // 只接受@SPI注解的类
            } else if (!withExtensionAnnotation(type)) {
                throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
            } else {
            //尝试从缓存中获取ExtensionLoader实力
                ExtensionLoader<T> loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
                if (loader == null) {
                //根据类型 创建ExtensionLoader
                    EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type));
                    loader = (ExtensionLoader)EXTENSION_LOADERS.get(type);
                }

                return loader;
            }
        }

上述代码通过传入的Class 类型的参数.判断该类型必须是接口类型,而且是被==@SPI== 注解标识的接口,在获取ExtensionLoader 实例时,先从静态缓存中获取,如果没有,就执行 new ExtensionLoader(type) 创建新的类型
接下来看 new ExtensionLoader(type)

//ExtensionLoader 构造函数
private ExtensionLoader(Class<?> type) {
        this.type = type;
        //如果传入的类型是ExtensionFactory则返回为null,否则就调用getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
        this.objectFactory = type == ExtensionFactory.class ? null : (ExtensionFactory)getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
    }

这里的 objectFactory 是一个ExtensionFactory 类型的属性. 如果该类型为null,则需要重新构建.

来看看 getExtensionLoader(ExtensionFactory.class) 方法的不就是刚开始我们进入的方法吗,来看下ExtensionFactory.class
在这里插入图片描述
可以看出来 ExtensionFactory 被@SPI 标注 而且对应的实现类 有 AdaptiveExtensionFactorySpiExtensionFactory 以及 SpringExtensiionFactory

在所有的ExtensionFactory 实现类中,只有 AdaptiveExtensionFactory@Adaptive标注, 标识是默认实现.

@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
    private final List<ExtensionFactory> factories;

    public AdaptiveExtensionFactory() {
    	// 构造方法中,获取 ExtensionFactory 的 ExtensionLoader
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List<ExtensionFactory> list = new ArrayList();
        //  将所有ExtensionFactory实现保存起来
        Iterator var3 = loader.getSupportedExtensions().iterator();

        while(var3.hasNext()) {
            String name = (String)var3.next();
            list.add(loader.getExtension(name));
        }

        this.factories = Collections.unmodifiableList(list);
    }
	//根据 类型 和名称获取
    public <T> T getExtension(Class<T> type, String name) {
        Iterator var3 = this.factories.iterator();

        Object extension;
        do {
            if (!var3.hasNext()) {
                return null;
            }
		 // 依次遍历各个ExtensionFactory实现的getExtension方法,一旦获取到Extension即返回
        // 如果遍历完所有的ExtensionFactory实现均无法找到Extension,则返回null
            ExtensionFactory factory = (ExtensionFactory)var3.next();
            extension = factory.getExtension(type, name);
        } while(extension == null);

        return extension;
    }
}

AdaptiveExtensionFactory他会遍历当前系统中所有的ExtensionFactory实现来获取指定的扩展实现,获取到扩展实现或遍历完所有的ExtensionFactory实现。这里调用了ExtensionLoader的getSupportedExtensions方法来获取ExtensionFactory的所有实现,又回到了ExtensionLoader类

接下来看一下 getAdaptiveExtension() 的实现

//
 public T getAdaptiveExtension() {
 		//private final Holder<Object> cachedAdaptiveInstance = new Holder();
 		// 这个 Holder 中相当于一个对象中只可以存储一份变量 相当于对当前对象的保护
        Object instance = this.cachedAdaptiveInstance.get();
        if (instance == null) {
        //如果 Holder中的对象不存在,而且 存在error 则直接抛出异常
            if (this.createAdaptiveInstanceError != null) {
                throw new IllegalStateException("fail to create adaptive instance: " + this.createAdaptiveInstanceError.toString(), this.createAdaptiveInstanceError);
            }
			//加锁 防止并发时重复创建对象.
            synchronized(this.cachedAdaptiveInstance) {
                instance = this.cachedAdaptiveInstance.get();
                if (instance == null) {
                //双重校验,进一步防止代码在执行过程中,对象被创建
                    try {
                    //没有缓存的实例,则通过该方法创建.  
                        instance = this.createAdaptiveExtension();
                        this.cachedAdaptiveInstance.set(instance);
                    } catch (Throwable var5) {
                        this.createAdaptiveInstanceError = var5;
                        throw new IllegalStateException("fail to create adaptive instance: " + var5.toString(), var5);
                    }
                }
            }
        }

        return instance;
    }

getAdaptiveExtension() 方法是先通过缓存Holder获取对应的类型,返回参数为T 其实根据 this.objectFactory = type == ExtensionFactory.class ? null : (ExtensionFactory)getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension(); 确认得到的类型. 如果类型不存在,则需要调用createAdaptiveExtension 进行创建.


 private T createAdaptiveExtension() {
        try {
        	//先后去getAdaptiveExtensionClass 实例  然后在注入处理
            return this.injectExtension(this.getAdaptiveExtensionClass().newInstance());
        } catch (Exception var2) {
            throw new IllegalStateException("Can not create adaptive extension " + this.type + ", cause: " + var2.getMessage(), var2);
        }
    }
    private Class<?> getAdaptiveExtensionClass() {
    getExtensionClasses(); // 加载当前Extension的所有实现,如果有@Adaptive类型,则会赋值为cachedAdaptiveClass属性缓存起来
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    return cachedAdaptiveClass = createAdaptiveExtensionClass(); // 没有找到@Adaptive类型实现,则动态创建一个AdaptiveExtensionClass
}

private Map<String, Class<?>> getExtensionClasses() {
    Map<String, Class<?>> classes = cachedClasses.get(); // 判断是否已经加载了当前Extension的所有实现类
    if (classes == null) {
        synchronized (cachedClasses) {
            classes = cachedClasses.get();
            if (classes == null) {
                classes = loadExtensionClasses(); // 如果还没有加载Extension的实现,则进行扫描加载,完成后赋值给cachedClasses变量
                cachedClasses.set(classes);
            }
        }
    }
    return classes;
}
    
     private Map<String, Class<?>> loadExtensionClasses() {
     //获取SPI注解信息
        SPI defaultAnnotation = (SPI)this.type.getAnnotation(SPI.class);
        if (defaultAnnotation != null) {
       		// 获取SPI 中的Value
            String value = defaultAnnotation.value();
            if ((value = value.trim()).length() > 0) {
            //value不为空而且有分割符号存在 则抛出异常
                String[] names = NAME_SEPARATOR.split(value);
                if (names.length > 1) {
                    throw new IllegalStateException("more than 1 default extension name on extension " + this.type.getName() + ": " + Arrays.toString(names));
                }
				// 选择SPI注入的value的name
                if (names.length == 1) {
                    this.cachedDefaultName = names[0];
                }
            }
        }
		//然后在对应的 目录下寻找key为 SPI中注入的Value值的对象,并加载 
        Map<String, Class<?>> extensionClasses = new HashMap();
        this.loadDirectory(extensionClasses, "META-INF/dubbo/internal/");
        this.loadDirectory(extensionClasses, "META-INF/dubbo/");
        this.loadDirectory(extensionClasses, "META-INF/services/");
        return extensionClasses;
    }
    /**
    * 加载目录下的 key value 
    */
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) {
        String fileName = dir + this.type.getName();

        try {
            ClassLoader classLoader = findClassLoader();
            Enumeration urls;
            if (classLoader != null) {
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }

            if (urls != null) {
                while(urls.hasMoreElements()) {
                    java.net.URL resourceURL = (java.net.URL)urls.nextElement();
                    this.loadResource(extensionClasses, classLoader, resourceURL);
                }
            }
        } catch (Throwable var7) {
            logger.error("Exception when load extension class(interface: " + this.type + ", description file: " + fileName + ").", var7);
        }

    }

这里的步骤总结起来便是这样的

  1. 首先判断是否已经有缓存的实例对象,如果没有则需要创建AdaptiveExtensionClass实例
  2. 通过getExtensionClasses() 加载当前Extension的所有实现,如果有@Adaptive类型,则会赋值为cachedAdaptiveClass属性缓存起来
  3. 判断是否已经加载了当前Extension的所有实现类,如果有则执行
  4. 如果还没有加载Extension的实现,则进行扫描( “META-INF/dubbo/internal/”,“META-INF/dubbo/”,“META-INF/services/”)加载,完成后赋值给cachedClasses变量
  5. 执行injectExtension 注入加载到的Key/value
private T injectExtension(T instance) {
    try {
        if (objectFactory != null) {
            for (Method method : instance.getClass().getMethods()) {
                if (method.getName().startsWith("set")
                        && method.getParameterTypes().length == 1
                        && Modifier.isPublic(method.getModifiers())) {// 处理所有set方法
                    Class<?> pt = method.getParameterTypes()[0];// 获取set方法参数类型
                    try {
                        // 获取setter对应的property名称
                        String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                        Object object = objectFactory.getExtension(pt, property); // 根据类型,名称信息从ExtensionFactory获取
                        if (object != null) { // 如果不为空,说set方法的参数是扩展点类型,那么进行注入
                            method.invoke(instance, object);
                        }
                    } catch (Exception e) {
                        logger.error("fail to inject via method " + method.getName()
                                + " of interface " + type.getName() + ": " + e.getMessage(), e);
                    }
                }
            }
        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return instance;
}

这里可以看到,扩展点自动注入的一句就是根据setter方法对应的参数类型和property名称从ExtensionFactory中查询,如果有返回扩展点实例,那么就进行注入操作。到这里getAdaptiveExtension方法就分析完毕了。

总结

  • 每个ExtensionLoader 实例只负责加载一个特定扩展点实现
  • 每个扩展点对应最多只有一个ExtensionLoader 实例
  • 对于每个扩展点实现,最多只会有一个实例
  • 一个扩展点实现可以对应多个名称(逗号分隔)
  • 对于需要等到运行时才能决定使用哪一个具体实现的扩展点,应获取其自使用扩展点实现(AdaptiveExtension )
  • @Adaptive 注解要么注释在扩展点==@SPI== 的方法上,要么注释在其实现类的类定义上
  • 每个扩展点最多只能有一个被AdaptiveExtension
  • 每个扩展点可以有多个可自动激活的扩展点实现(使用==@Activate==注解保证加载哪一个)
  • 由于每个扩展点实现最多只有一个实例,因此扩展点实现应保证线程安全
  • 如果扩展点有多个Wrapper,那么最终其执行的顺序不确定(内部使用ConcurrentHashSet存储)

参考文章:
https://blog.csdn.net/jdluojing/article/details/44947221

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值