zoukankan      html  css  js  c++  java
  • dubbo源码分析3——SPI机制中的ExtensionLoader类的objectFactory属性分析

    ExtensionLoader类是整个SPI的核心类,每个SPI都会对应一个ExtensionLoader类实例,这个类的构造方法如下:

    private ExtensionLoader(Class<?> type) {
            this.type = type;
            objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
        }

     里面的objectFactory对应的就是ExtensionFactory类的实例,通过源码能发现,ExtensionFactory自身也是一个SPI接口,那么它也会有一个对应的ExtensionLoader类实例,这个类实例中的objectFactory属性为null ,而其他的ExtensionLoader类实例中的 objectFactory属性是 : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()

    我们就先来分析下ExtensionLoader.getExtensionLoader(ExtensionFactory.class) 这句代码。

    // 先通过type从缓存中获取ExtensionLoader,如果缓存中不存在,则创建相应的ExtensionLoader放入缓存,再返回
    public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { if (type == null) throw new IllegalArgumentException("Extension type == null"); if(!type.isInterface()) { throw new IllegalArgumentException("Extension type(" + type + ") is not interface!"); } if(!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!"); } ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; }

    getAdaptiveExtension()内部的调用过程如下(注意这是一个实例方法):

    -> if(cachedAdaptiveInstance.get() == null){ createAdaptiveExtension() }

          ->getAdaptiveExtensionClass()   //下面的调用有两个分支

                  // 分支1
        ->getExtensionClasses()
          ->loadExtensionClasses()
            ->loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);

            injectExtension   //完成注入,这是 ExtensionFactory 类的作用之所在 

                   // 分支2

                   ->createAdaptiveExtensionClass()

                      injectExtension 

    经过上述分析,可以得出 ExtensionLoader.getExtensionLoader(ExtensionFactory.class) 返回的是 com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory类的实例,这个类在ExtensionFactory的SPI描述文件中的第二行

    spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
    adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
    spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory

     AdaptiveExtensionFactory的源码如下

    @Adaptive
    public class AdaptiveExtensionFactory implements ExtensionFactory {
        
        private final List<ExtensionFactory> factories;
        
        public AdaptiveExtensionFactory() {
            ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
            List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
            for (String name : loader.getSupportedExtensions()) {
                list.add(loader.getExtension(name));
            }
            factories = Collections.unmodifiableList(list);
        }
    
        public <T> T getExtension(Class<T> type, String name) {
            for (ExtensionFactory factory : factories) {
                T extension = factory.getExtension(type, name);
                if (extension != null) {
                    return extension;
                }
            }
            return null;
        }
    
    }

     总结:

             通过上述分析,可以知道:

             1. 除了ExtensionFactory之外,其他的SPI接口对应的ExtensionLoader类实例中的 objectFactory属性都是AdaptiveExtensionFactory的实例对象。

             2.  且这些AdaptiveExtensionFaatory实例都是同一个,这是因为ExtensionLoader的类属性会会在EXTENSION_LOADERS中缓存创建好的loader,每个loader又会在其的实例属性cachedAdaptiveClass缓存这个adaptive性质的Extension类。

             3.  ExtensionLoader的injectExtension方法完成的注入工作正是objectFactory(ExtensionFactory类)的真正作用。这个作用留待下一篇再做分析。 

  • 相关阅读:
    php 本周的起始时间
    获取微信公众号素材模板id
    复活贴
    Net 4.0 Parallel 编程(四) Task(上)
    Windows Phone 实用开发技巧120合集(电子书+源代码)
    Net 4.0 Parallel 编程(九)Task中的数据共享(下)
    收藏别人的小类库
    将DLL程序集加入GAC后的一系列问题汇总,及解决方法
    Net 4.0 Parallel 编程(七)Task中的数据共享(上)
    内存做硬盘,开启readyboost加速,全面提升系统性能!
  • 原文地址:https://www.cnblogs.com/hzhuxin/p/7543990.html
Copyright © 2011-2022 走看看