扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
如何理解dubbo的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
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-common-2.7.3-sources.jar!/org/apache/dubbo/common/extension/support/ActivateComparator.java
public class ActivateComparator implements Comparator
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问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注创新互联行业资讯频道了解更多相关知识。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流