千家信息网

如何理解dubbo的ExtensionLoader.getActivateExtension

发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,如何理解dubbo的ExtensionLoader.getActivateExtension,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的
千家信息网最后更新 2025年12月03日如何理解dubbo的ExtensionLoader.getActivateExtension

如何理解dubbo的ExtensionLoader.getActivateExtension,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

主要研究一下dubbo的ExtensionLoader.getActivateExtension

ExtensionLoader.getActivateExtension

dubbo-2.7.3/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java

public class ExtensionLoader {    private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);    private static final String SERVICES_DIRECTORY = "META-INF/services/";    private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";    private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";    //......    /**     * This is equivalent to {@code getActivateExtension(url, url.getParameter(key).split(","), null)}     *     * @param url   url     * @param key   url parameter key which used to get extension point names     * @param group group     * @return extension list which are activated.     * @see #getActivateExtension(org.apache.dubbo.common.URL, String[], String)     */    public List getActivateExtension(URL url, String key, String group) {        String value = url.getParameter(key);        return getActivateExtension(url, StringUtils.isEmpty(value) ? null : COMMA_SPLIT_PATTERN.split(value), group);    }    /**     * Get activate extensions.     *     * @param url    url     * @param values extension point names     * @param group  group     * @return extension list which are activated     * @see org.apache.dubbo.common.extension.Activate     */    public List getActivateExtension(URL url, String[] values, String group) {        List exts = new ArrayList<>();        List names = values == null ? new ArrayList<>(0) : Arrays.asList(values);        if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) {            getExtensionClasses();            for (Map.Entry entry : cachedActivates.entrySet()) {                String name = entry.getKey();                Object activate = entry.getValue();                String[] activateGroup, activateValue;                if (activate instanceof Activate) {                    activateGroup = ((Activate) activate).group();                    activateValue = ((Activate) activate).value();                } else if (activate instanceof com.alibaba.dubbo.common.extension.Activate) {                    activateGroup = ((com.alibaba.dubbo.common.extension.Activate) activate).group();                    activateValue = ((com.alibaba.dubbo.common.extension.Activate) activate).value();                } else {                    continue;                }                if (isMatchGroup(group, activateGroup)) {                    T ext = getExtension(name);                    if (!names.contains(name)                            && !names.contains(REMOVE_VALUE_PREFIX + name)                            && isActive(activateValue, url)) {                        exts.add(ext);                    }                }            }            exts.sort(ActivateComparator.COMPARATOR);        }        List usrs = new ArrayList<>();        for (int i = 0; i < names.size(); i++) {            String name = names.get(i);            if (!name.startsWith(REMOVE_VALUE_PREFIX)                    && !names.contains(REMOVE_VALUE_PREFIX + name)) {                if (DEFAULT_KEY.equals(name)) {                    if (!usrs.isEmpty()) {                        exts.addAll(0, usrs);                        usrs.clear();                    }                } else {                    T ext = getExtension(name);                    usrs.add(ext);                }            }        }        if (!usrs.isEmpty()) {            exts.addAll(usrs);        }        return exts;    }    private Map> getExtensionClasses() {        Map> classes = cachedClasses.get();        if (classes == null) {            synchronized (cachedClasses) {                classes = cachedClasses.get();                if (classes == null) {                    classes = loadExtensionClasses();                    cachedClasses.set(classes);                }            }        }        return classes;    }    // synchronized in getExtensionClasses    private Map> loadExtensionClasses() {        cacheDefaultExtensionName();        Map> extensionClasses = new HashMap<>();        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());        loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());        loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));        return extensionClasses;    }    private void loadDirectory(Map> extensionClasses, String dir, String type) {        String fileName = dir + type;        try {            Enumeration 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 resourceURL = urls.nextElement();                    loadResource(extensionClasses, classLoader, resourceURL);                }            }        } catch (Throwable t) {            logger.error("Exception occurred when loading extension class (interface: " +                    type + ", description file: " + fileName + ").", t);        }    }    private void loadResource(Map> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {        try {            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {                String line;                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) {                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);                            }                        } catch (Throwable t) {                            IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);                            exceptions.put(line, e);                        }                    }                }            }        } catch (Throwable t) {            logger.error("Exception occurred when loading extension class (interface: " +                    type + ", class file: " + resourceURL + ") in " + resourceURL, t);        }    }    private void loadClass(Map> extensionClasses, java.net.URL resourceURL, Class clazz, String name) throws NoSuchMethodException {        if (!type.isAssignableFrom(clazz)) {            throw new IllegalStateException("Error occurred when loading extension class (interface: " +                    type + ", class line: " + clazz.getName() + "), class "                    + clazz.getName() + " is not subtype of interface.");        }        if (clazz.isAnnotationPresent(Adaptive.class)) {            cacheAdaptiveClass(clazz);        } else if (isWrapperClass(clazz)) {            cacheWrapperClass(clazz);        } else {            clazz.getConstructor();            if (StringUtils.isEmpty(name)) {                name = findAnnotationName(clazz);                if (name.length() == 0) {                    throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);                }            }            String[] names = NAME_SEPARATOR.split(name);            if (ArrayUtils.isNotEmpty(names)) {                cacheActivateClass(clazz, names[0]);                for (String n : names) {                    cacheName(clazz, n);                    saveInExtensionClass(extensionClasses, clazz, n);                }            }        }    }    /**     * cache Activate class which is annotated with Activate     * 

* for compatibility, also cache class with old alibaba Activate annotation */ private void cacheActivateClass(Class clazz, String name) { Activate activate = clazz.getAnnotation(Activate.class); if (activate != null) { cachedActivates.put(name, activate); } else { // support com.alibaba.dubbo.common.extension.Activate com.alibaba.dubbo.common.extension.Activate oldActivate = clazz.getAnnotation(com.alibaba.dubbo.common.extension.Activate.class); if (oldActivate != null) { cachedActivates.put(name, oldActivate); } } } /** * Find the extension with the given name. If the specified name is not found, then {@link IllegalStateException} * will be thrown. */ @SuppressWarnings("unchecked") public T getExtension(String name) { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } if ("true".equals(name)) { return getDefaultExtension(); } final Holder holder = getOrCreateHolder(name); Object instance = holder.get(); if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { instance = createExtension(name); holder.set(instance); } } } return (T) instance; } //......}
  • getActivateExtension方法先执行getExtensionClasses加载extension类,这里主要通过loadDirectory方法加载META-INF/dubbo/、META-INF/dubbo/internal/、META-INF/services/三个目录下的extension

  • loadDirectory方法会调用loadResource方法,loadResource方法会调用loadClass方法,loadClass方法会通过cacheActivateClass把Activate注解信息放入到cachedActivates中

  • 之后遍历cachedActivates通过getExtension方法把extension实例放入exts,然后再根据ActivateComparator.COMPARATOR进行排序,最后加载usr的extension(目前看代码names貌似一直为空),然后合并返回

ActivateComparator

dubbo-common-2.7.3-sources.jar!/org/apache/dubbo/common/extension/support/ActivateComparator.java

public class ActivateComparator implements Comparator {    public static final Comparator COMPARATOR = new ActivateComparator();    @Override    public int compare(Object o1, Object o2) {        if (o1 == null && o2 == null) {            return 0;        }        if (o1 == null) {            return -1;        }        if (o2 == null) {            return 1;        }        if (o1.equals(o2)) {            return 0;        }        Class inf = findSpi(o1.getClass());        ActivateInfo a1 = parseActivate(o1.getClass());        ActivateInfo a2 = parseActivate(o2.getClass());        if ((a1.applicableToCompare() || a2.applicableToCompare()) && inf != null) {            ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(inf);            if (a1.applicableToCompare()) {                String n2 = extensionLoader.getExtensionName(o2.getClass());                if (a1.isLess(n2)) {                    return -1;                }                if (a1.isMore(n2)) {                    return 1;                }            }            if (a2.applicableToCompare()) {                String n1 = extensionLoader.getExtensionName(o1.getClass());                if (a2.isLess(n1)) {                    return 1;                }                if (a2.isMore(n1)) {                    return -1;                }            }        }        int n1 = a1 == null ? 0 : a1.order;        int n2 = a2 == null ? 0 : a2.order;        // never return 0 even if n1 equals n2, otherwise, o1 and o2 will override each other in collection like HashSet        return n1 > n2 ? 1 : -1;    }    private Class findSpi(Class clazz) {        if (clazz.getInterfaces().length <= 0) {            return null;        }        for (Class intf : clazz.getInterfaces()) {            if (intf.isAnnotationPresent(SPI.class)) {                return intf;            } else {                Class result = findSpi(intf);                if (result != null) {                    return result;                }            }        }        return null;    }    private ActivateInfo parseActivate(Class clazz) {        ActivateInfo info = new ActivateInfo();        if (clazz.isAnnotationPresent(Activate.class)) {            Activate activate = clazz.getAnnotation(Activate.class);            info.before = activate.before();            info.after = activate.after();            info.order = activate.order();        } else {            com.alibaba.dubbo.common.extension.Activate activate = clazz.getAnnotation(                    com.alibaba.dubbo.common.extension.Activate.class);            info.before = activate.before();            info.after = activate.after();            info.order = activate.order();        }        return info;    }    private static class ActivateInfo {        private String[] before;        private String[] after;        private int order;        private boolean applicableToCompare() {            return ArrayUtils.isNotEmpty(before) || ArrayUtils.isNotEmpty(after);        }        private boolean isLess(String name) {            return Arrays.asList(before).contains(name);        }        private boolean isMore(String name) {            return Arrays.asList(after).contains(name);        }    }}
  • ActivateComparator首先通过parseActivate解析注解信息到ActivateInfo,然后对于有配置before或after的则根据其值进行升序排序,否则则通过order(没有指定默认为0)来排序,大于返回1,否则返回-1

小结

  • getActivateExtension方法先执行getExtensionClasses加载extension类,这里主要通过loadDirectory方法加载META-INF/dubbo/、META-INF/dubbo/internal/、META-INF/services/三个目录下的extension

  • loadDirectory方法会调用loadResource方法,loadResource方法会调用loadClass方法,loadClass方法会通过cacheActivateClass把Activate注解信息放入到cachedActivates中

  • 之后遍历cachedActivates通过getExtension方法把extension实例放入exts,然后再根据ActivateComparator.COMPARATOR进行排序,最后加载usr的extension(目前看代码names貌似一直为空),然后合并返回

关于如何理解dubbo的ExtensionLoader.getActivateExtension问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。

方法 排序 信息 注解 问题 三个 代码 实例 更多 目录 帮助 解答 易行 简单易行 内容 升序 小伙 小伙伴 小结 知识 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 光伏电站网络安全预防措施 数据库怎么查表里有多少条数据 英雄联盟那个服务器在河北 java script绑定数据库 纽卡斯尔网络安全好毕业吗 山西量化积分管理软件开发系统 沈阳网络安全工程师 网络安全的主要指标有哪些 网络安全工程就业前景分析 油气场站的无线网络安全么 河北企业软件开发价格如何计算 iptv流媒体服务器说明书 山东网络卫星授时服务器云主机 网络安全是什么类型的 珠海哈利叔叔网络技术有限公司 数据库访问技术包括 国家网络安全的成就 网络安全和信息化英文怎么写 华为云服务器虚拟交换机 电脑怎么装不上数据库 c 连接数据库access 分布式数据库缓存 中小企业最多用的网络技术 智能化网络安全欢迎咨询 数据库常用的工具有哪些 网络安全跟信息化 国产cpu小型服务器 黑魂3捏脸女数据库 网络安全等级测评 山东 厄运峡谷服务器是什么游戏
0