ExtensionLoader擴(kuò)展點(diǎn)加載

官方文檔.png

在官方文檔中,提到擴(kuò)展點(diǎn)加載機(jī)制,不妨看看是如何實(shí)現(xiàn)的。
擴(kuò)展點(diǎn)加載機(jī)制,最重要的類就是ExtensionLoader。

getExtensionLoader的實(shí)現(xiàn)原理

在獲取擴(kuò)展加載器的時(shí)候,首先會判斷是否有注解SPI,沒有則拋異常,有SPI注解的前提下,先從緩存取,取不到,根據(jù)class類型新建一個(gè)新的擴(kuò)展點(diǎn)加載器。

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!");
        }
        //是否有SPI注解
        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) {
            根據(jù)類型新增一個(gè)擴(kuò)展點(diǎn)加載器
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }

在新增加載點(diǎn)擴(kuò)展器的時(shí)候,會根據(jù)class類型獲取一個(gè)運(yùn)行期自適應(yīng)的擴(kuò)展類型

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

我們看到,如果類型不是ExtensionFactory,則從ExtensionFactory的擴(kuò)展加載器中獲取一個(gè)可擴(kuò)展的的加載器。這里先不看ExtensionFactory,先看一下獲取可擴(kuò)展加載器方法。

getAdaptiveExtension獲取可調(diào)整的擴(kuò)展加載器

在獲取可擴(kuò)展加載器的時(shí)候,先從緩存獲取,若緩存不存在,創(chuàng)建新的擴(kuò)展加載器。在創(chuàng)建新的擴(kuò)展加載器的時(shí)候,首先判斷配置文件中(META-INF/dubbo/,META-INF/services/,META-INF/dubbo/internal)配置的class是否有被Adaptive注解的類,如果有,則直接返回被注解Adaptive的可擴(kuò)展加載類,如果沒有,則生成一個(gè)擴(kuò)展類。

public T getAdaptiveExtension() {
        //先從緩存中獲取
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
            if (createAdaptiveInstanceError == null) {
                synchronized (cachedAdaptiveInstance) {
                    instance = cachedAdaptiveInstance.get();
                    if (instance == null) {
                        try {
                            //創(chuàng)建一個(gè)新的可擴(kuò)展加載器
                            instance = createAdaptiveExtension();
                            cachedAdaptiveInstance.set(instance);
                        } catch (Throwable t) {
                            createAdaptiveInstanceError = t;
                            throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
                        }
                    }
                }
            } else {
                throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
            }
        }
        return (T) instance;
    }
    private T createAdaptiveExtension() {
         //根據(jù)可擴(kuò)展實(shí)例做擴(kuò)展
        try {
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }

   //獲取可擴(kuò)展實(shí)例
    private Class<?> getAdaptiveExtensionClass() {
      // 加載當(dāng)前Extension的所有實(shí)現(xiàn),如果有@Adaptive類型,則會賦值為cachedAdaptiveClass屬性緩存起來
        getExtensionClasses();
        if (cachedAdaptiveClass != null) {
            //如果緩存有可擴(kuò)展類,則直接返回
            return cachedAdaptiveClass;
        }
        //緩存中不存在創(chuàng)建一個(gè)
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }

 獲取可擴(kuò)展類 
 private Map<String, Class<?>> getExtensionClasses() {
        Map<String, Class<?>> classes = cachedClasses.get();
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                if (classes == null) {
                    //如果沒有,則從文件中加載
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }

  從配置文件中加載
  private Map<String, Class<?>> loadExtensionClasses() {
        final SPI defaultAnnotation = type.getAnnotation(SPI.class);
         //忽略1w行代碼
        // 文件路徑: 
        loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
        //文件路徑
        loadFile(extensionClasses, DUBBO_DIRECTORY);
        //文件路徑 
        loadFile(extensionClasses, SERVICES_DIRECTORY);
        return extensionClasses;
    }
//根據(jù)文件名(包路徑)查找所有文件,將每一行的配置讀取出來,判斷是否是實(shí)現(xiàn)該接口的類,如果接口中有注解`Adaptive`,則更新`cachedAdaptiveClass`的值。
private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
   //文件路徑為基本路徑+包路徑
   String fileName = dir + type.getName();
        try {
            Enumeration<java.net.URL> urls;
            ClassLoader classLoader = findClassLoader();
            if (classLoader != null) {
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }
            if (urls != null) {
                while (urls.hasMoreElements()) {
                    java.net.URL url = urls.nextElement();
                    try {
                        //讀文件
                        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
                        //讀每一行數(shù)據(jù),判斷=之前為bean的ID,后面為bean的class類型
                        try {
                            String line = null;
                            while ((line = reader.readLine()) != null) {
                                final int ci = line.indexOf('#');
                                if (ci >= 0) line = line.substring(0, ci);
                                line = line.trim();
                                if (line.length() > 0) {
                                    try {
                                        String name = null;
                                        int i = line.indexOf('=');
                                        if (i > 0) {
                                            name = line.substring(0, i).trim();
                                            line = line.substring(i + 1).trim();
                                        }
                                        if (line.length() > 0) {
                                            Class<?> clazz = Class.forName(line, true, classLoader);
                                            if (!type.isAssignableFrom(clazz)) {
                                                //如果類不是實(shí)現(xiàn)該接口的實(shí)例,則啟動報(bào)錯(cuò)
                                                throw new IllegalStateException("Error when load extension class(interface: " +
                                                        type + ", class line: " + clazz.getName() + "), class "
                                                        + clazz.getName() + "is not subtype of interface.");
                                            }
                                            if (clazz.isAnnotationPresent(Adaptive.class)) {
                                                //如果該類注解了Adaptive注解,則更新cachedAdaptiveClass為class。
                                                if (cachedAdaptiveClass == null) {
                                                    cachedAdaptiveClass = clazz;
                                                } else if (!cachedAdaptiveClass.equals(clazz)) {
                                                    throw new IllegalStateException("More than 1 adaptive class found: "
                                                            + cachedAdaptiveClass.getClass().getName()
                                                            + ", " + clazz.getClass().getName());
                                                }
                                            } else {
                                                try {
                                                    clazz.getConstructor(type);
                                                    Set<Class<?>> wrappers = cachedWrapperClasses;
                                                    if (wrappers == null) {
                                                        cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
                                                        wrappers = cachedWrapperClasses;
                                                    }
                                                    wrappers.add(clazz);
                                                } catch (NoSuchMethodException e) {
                                                    clazz.getConstructor();
                                                    if (name == null || name.length() == 0) {
                                                        name = findAnnotationName(clazz);
                                                        if (name == null || name.length() == 0) {
                                                            if (clazz.getSimpleName().length() > type.getSimpleName().length()
                                                                    && clazz.getSimpleName().endsWith(type.getSimpleName())) {
                                                                name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase();
                                                            } else {
                                                                throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url);
                                                            }
                                                        }
                                                    }
                                                    String[] names = NAME_SEPARATOR.split(name);
                                                    if (names != null && names.length > 0) {
                                                        Activate activate = clazz.getAnnotation(Activate.class);
                                                        if (activate != null) {
                                                            cachedActivates.put(names[0], activate);
                                                        }
                                                        for (String n : names) {
                                                            if (!cachedNames.containsKey(clazz)) {
                                                                cachedNames.put(clazz, n);
                                                            }
                                                            Class<?> c = extensionClasses.get(n);
                                                            if (c == null) {
                                                                extensionClasses.put(n, clazz);
                                                            } else if (c != clazz) {
                                                                throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    } catch (Throwable t) {
                                        IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
                                        exceptions.put(line, e);
                                    }
                                }
                            } // end of while read lines
                        } finally {
                            reader.close();
                        }
                    } catch (Throwable t) {
                        logger.error("Exception when load extension class(interface: " +
                                type + ", class file: " + url + ") in " + url, t);
                    }
                } // end of while urls
            }
        } catch (Throwable t) {
            logger.error("Exception when load extension class(interface: " +
                    type + ", description file: " + fileName + ").", t);
        }

如果沒有被注解Adaptive注解的,則直接創(chuàng)建一個(gè)新的可擴(kuò)展加載類。

 private Class<?> createAdaptiveExtensionClass() {
        //創(chuàng)建可擴(kuò)展加載器的代碼。。
        String code = createAdaptiveExtensionClassCode();
        //獲取類加載器
        ClassLoader classLoader = findClassLoader();
        //獲取編輯器
        com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        //將代碼編譯為可擴(kuò)展類
        return compiler.compile(code, classLoader);
    }

在對可擴(kuò)展實(shí)例做擴(kuò)展,會根據(jù)代理工廠創(chuàng)建一個(gè)實(shí)例,在構(gòu)造方法中,使用的是ExtensionFactory的擴(kuò)展

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())) {
                        Class<?> pt = method.getParameterTypes()[0];
                        try {
                            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                            //獲取擴(kuò)展實(shí)例
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                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;
    } 

看一下 ExtensionFactory的定義,和實(shí)現(xiàn)

@SPI
public interface ExtensionFactory {
   <T> T getExtension(Class<T> type, String name);
}


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

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

}


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

}

很顯然,在這里用到的是AdaptiveExtensionFactory,因?yàn)樗蛔⒔?code>@Adaptive注解了,然后從ExtensionFactory中獲取擴(kuò)展加載類。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容