dubbo源碼分析4——SPI機制_ExtensionFactory類的作用


ExtensionFactory的源碼:

@SPI
public interface ExtensionFactory {

    /**
     * Get extension.
     * 
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);

}

ExtensionFactory的作用就類似spring框架中的IOC的作用,正是因為JDK的SPI機制比較簡單,所以duboo框架才重寫了SPI機制,並實現了IOC和AOP的功能。本篇先介紹它的IOC的功能,根據上篇的分析可知,IOC功能的代碼出現在ExtensionLoader的 injectExtension方法里面,我們就先來分析這個方法,先列出兩段源碼:

觸發調用injectExtension方法的源碼:

private T createExtension(String name) {
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            injectExtension(instance);  //完成IOC的依賴注入
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (wrapperClasses != null && wrapperClasses.size() > 0) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
                    type + ")  could not be instantiated: " + t.getMessage(), t);
        }
    }
    

 injectExtension方法的源碼:

private T injectExtension(T instance) {  //instanceSPI實現類的實例對象 

    try {
      
if (objectFactory != null) {
          //獲取instance的所有方法, for (Method method : instance.getClass().getMethods()) {
            //找出滿足三要素條件的方法(1.set為前綴的 2.方法參數為1個的 3.是public的方法)
if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { Class<?> pt = method.getParameterTypes()[0]; //獲取要 set的類型 try {
                 //取出要 set的屬性名 String property
= method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; Object object = objectFactory.getExtension(pt, property); //調用ExtensionFactory的
getExtension方法獲取要set的對象               
                
                
//此時我們就可以將
ExtensionFactory看作容器,判斷這個要set的屬性在容器中是否存在
                if (object != null) { 
                  method.invoke(instance, object);   //執行set方法,完成一個屬性的注入
                }
              }
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;
}

上面的源碼通過注釋已經把injectExtension 方法分析的很清楚了,下面只需要再分析下AdaptiveExtensionFactory類的源碼就可以了,原因上篇文章也寫明了,因為所有的SPI類(除ExtensionFactory之外)對應的ExtensionLoader實例的objectFactory屬性的類型都是AdaptiveExtensionFactory類

AdaptiveExtensionFactory類的構造方法分析: 

 根據 loadFile()方法的緩存原則,AdaptiveExtensionFactory實例中的factories的size返回應為2,里面只會保存這兩個類實例:

    spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

  spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory

因為adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory是保存在cachedAdaptiveClass上的

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);
    }

 

這樣我們只要分析清楚AdaptiveExtensionFactory類的getExtension方法,就可以明白這個IOC容器是如何取出需要的SPI實例依賴了

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;
    }

從上述代碼上看其實就去調用下面這兩個類的getExtension(type, name)方法

com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory

SpringExtensionFactory的源碼:

public class SpringExtensionFactory implements ExtensionFactory {
    
    private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
    
    public static void addApplicationContext(ApplicationContext context) {
        contexts.add(context);
    }

    public static void removeApplicationContext(ApplicationContext context) {
        contexts.remove(context);
    }

    @SuppressWarnings("unchecked")
//這個比較容易理解,就是從spring的容器中去獲取
public <T> T getExtension(Class<T> type, String name) { for (ApplicationContext context : contexts) { if (context.containsBean(name)) { Object bean = context.getBean(name); if (type.isInstance(bean)) { return (T) bean; } } } return null; } }

 

SpiExtensionFactory的源碼 :

 看了這個方法真是覺的挺繞的,明明先是ExtensionLoader在注入時找自己的 objectFactory ( 即ExtensionFactory)來幫忙,結果objectFactory的這個實現,又把鍋甩回給了loader.getAdaptiveExtension()方法,由於這個getAdaptiveExtension就又回到了之前講過的一個調用過程,這里再列一下:

getAdaptiveExtension()內部的調用過程如下(注意這是一個實例方法):

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

      ->getAdaptiveExtensionClass()   //下面的調用有兩個分支

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

        injectExtension   //完成注入,這是 ExtensionFactory 類的作用之所在 

               // 分支2

               ->createAdaptiveExtensionClass()

                  injectExtension 

public class SpiExtensionFactory implements ExtensionFactory {

    public <T> T getExtension(Class<T> type, String name) {
        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
            if (loader.getSupportedExtensions().size() > 0) {
                return loader.getAdaptiveExtension();
            }
        }
        return null;
    }

}

 

總結:

   通過跟蹤源碼,以目前的這幾個實現類而言,SpiExtensionFactory其實啥都沒干,最后還是loader.getAdaptiveExtension()方法在負責IOC,SpiExtensionFactory只可以理解成是一個門面類的作用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM