千家信息网

如何理解dubbo的ExtensionLoader.getActivateExtension

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,如何理解dubbo的ExtensionLoader.getActivateExtension,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的
千家信息网最后更新 2026年11月04日如何理解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安全错误 数据库的锁怎样保障安全 互联网高科技 百单网互联网科技有限公司怎么样 广东万易互联网科技有限公司惠州分公司 苏州找大状互联网科技有限公司 上海喔噻互联网科技 新浪科技互联网 互联网金融 科技创新 狮子座互联网科技培训 老年人脱离互联网科技的作文 现代科技和互联网有关系吗 隆华科技工业互联网 注册互联网科技公司经营范围大全 坤平互联网科技 健康食品互联网创新科技园项目 有人说阿里系是互联网科技企业 图游互联网科技 山东大美朱楼互联网科技有限公司 全球科技与互联网公司市值变化 陕西彩京云互联网科技有限公司 青岛互联网科技园 广州淘业互联网络科技 重庆互联网络科技 广西互联网科技公司 济南华为互联网科技产业总部基地 广州慧亚互联网科技怎么样 广东工业互联网大赛深圳学泰科技 黑云互联网科技有限公司 西安有哪些互联网高科技企业 互联网科技平台产品运营 小牛互联网科技有限公司地址
0