Dubbo进阶(七):Dubbo扩展点加载机制(下)

在上一篇文章Dubbo进阶(六):Dubbo扩展点加载机制(中)中介绍了扩展点机制的一些注解,这篇文章主要通过源码来学习一下ExtensionLoader的原理。ExtensionLoader是整个扩展机制的主要逻辑,在这个类里实现了配置的加载、扩展类缓存、自适应对象生成等所有工作。

ExtensionLoader的工作流程

ExtensionLoader的逻辑入口可以分为getExtensiongetAdaptiveExtensiongetActivateExtension三个,分别是获取普通扩展类、获取自动适应扩展类和获取自动激活扩展类。

在这里插入图片描述

getExtension的实现原理
// 根据name获取扩展点实现的实例
public T getExtension(String name) {
    // 如果没有给出指定的name,抛出异常
    if (StringUtils.isEmpty(name)) {
        throw new IllegalArgumentException("Extension name == null");
    }
    // 如果name=true,则返回默认的扩展类
    if ("true".equals(name)) {
   		// 详细逻辑请看下面第二段代码块
        return getDefaultExtension();
    }
    // 获取扩展对象,Holder里的value属性保存着扩展对象实例
    final Holder<Object> 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;
}

---------------------第二段代码块,华丽丽的分割线------------------------

接下来是获取默认extension的逻辑。

public T getDefaultExtension() {
    // 加载默认
    getExtensionClasses();
    if (StringUtils.isBlank(cachedDefaultName) || "true".equals(cachedDefaultName)) {
        return null;
    }
    return getExtension(cachedDefaultName);
}
private Map<String, Class<?>> getExtensionClasses() {
    // 尝试先从缓存中获取classes
    Map<String, Class<?>> classes = cachedClasses.get();
    // 如果缓存中没有,则开始加载class
    if (classes == null) {
        synchronized (cachedClasses) {
            classes = cachedClasses.get();
            if (classes == null) {
                classes = loadExtensionClasses();
                cachedClasses.set(classes);
            }
        }
    }
    return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
    // 检查是否有@SPI注解,如果有则获取注解中的名字并缓存为默认的实现。
    cacheDefaultExtensionName();

    Map<String, Class<?>> extensionClasses = new HashMap<>();

    for (LoadingStrategy strategy : strategies) {
        // 加载配置文件
        loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
        // 由于 Dubbo 迁到 apache ,所以包名有变化,会替换之前的 alibaba 为 apache
        loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
    }

    return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
                           boolean extensionLoaderClassLoaderFirst, String... excludedPackages) {
    // 获取文件在项目中的路径,如:META-INF/dubbo/top.ytao.demo.spi.AnimalService
    String fileName = dir + type;
    try {
        Enumeration<java.net.URL> urls = null;
        ClassLoader classLoader = findClassLoader();

        // 加载内部扩展类
        if (extensionLoaderClassLoaderFirst) {
            ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
            if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
                urls = extensionLoaderClassLoader.getResources(fileName);
            }
        }

        // 加载当前 fileName 文件
        if(urls == null || !urls.hasMoreElements()) {
            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, excludedPackages);
            }
        }
    } catch (Throwable t) {
        logger.error("Exception occurred when loading extension class (interface: " +
                type + ", description file: " + fileName + ").", t);
    }
}
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
                          java.net.URL resourceURL, String... excludedPackages) {
    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('=');
                        // 如果当前行存在 "=",将 "=" 左右的值分开复制给 name 和 line
                        if (i > 0) {
                            name = line.substring(0, i).trim();
                            line = line.substring(i + 1).trim();
                        }
                        if (line.length() > 0 && !isExcluded(line, excludedPackages)) {
                            // 加载扩展类
                            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<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
    // 检查当前实现类是否实现了 type 接口
    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.");
    }
    // 当前实现类是否有 Adaptive 注解
    if (clazz.isAnnotationPresent(Adaptive.class)) {
        cacheAdaptiveClass(clazz);
        // 当前类是否为 Wrapper 包装扩展类
    } else if (isWrapperClass(clazz)) {
        cacheWrapperClass(clazz);
    } else {
        // 尝试当前类是否有无参构造方法
        clazz.getConstructor();
        if (StringUtils.isEmpty(name)) {
            // 如果 name 为空,则获取 clazz 的 @Extension 注解的值,如果注解值也没有,则使用小写类名
            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)) {
            // 缓存 扩展名和@Activate的缓存
            cacheActivateClass(clazz, names[0]);
            for (String n : names) {
                cacheName(clazz, n);
                // 将 扩展类和扩展名 保存到extensionClasses 扩展名->扩展类 关系映射中
                saveInExtensionClass(extensionClasses, clazz, n);
            }
        }
    }
}

---------------------第二段代码块,华丽丽的分割线------------------------

---------------------第三段代码块,华丽丽的分割线------------------------

创建扩展对象的逻辑如下

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, clazz.newInstance());
            instance = (T) EXTENSION_INSTANCES.get(clazz);
        }
        // 向当前实例注入依赖
        injectExtension(instance);
        // 获取包装扩展类缓存
        Set<Class<?>> wrapperClasses = cachedWrapperClasses;
        if (CollectionUtils.isNotEmpty(wrapperClasses)) {
            for (Class<?> wrapperClass : wrapperClasses) {
                // 创建包装扩展类实例,并向其注入依赖
                instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
            }
        }
        // 初始化扩展对象
        initExtension(instance);
        return instance;
    } catch (Throwable t) {
        throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                type + ") couldn't be instantiated: " + t.getMessage(), t);
    }
}

依赖注入的实现

private T injectExtension(T instance) {

    if (objectFactory == null) {
        return instance;
    }

    try {
        // 遍历当前扩展类的全部方法,如果当前方法不属于 setter 方法,
        // 即不是以 'set'开头的方法名,参数不是一个的,该方法访问级别不是 public 的,则不往下执行
        for (Method method : instance.getClass().getMethods()) {
            if (!isSetter(method)) {
                continue;
            }
            /**
             * Check {@link DisableInject} to see if we need auto injection for this property
             */
            // 当前方法是否添加了不要注入依赖的注解
            if (method.getAnnotation(DisableInject.class) != null) {
                continue;
            }
            Class<?> pt = method.getParameterTypes()[0];
            if (ReflectUtils.isPrimitives(pt)) {
                continue;
            }

            try {
                // 通过属性 setter 方法获取属性名
                String property = getSetterProperty(method);
                // 获取依赖对象
                Object object = objectFactory.getExtension(pt, property);
                if (object != null) {
                    // 设置依赖
                    method.invoke(instance, object);
                }
            } catch (Exception e) {
                logger.error("Failed to inject via method " + method.getName()
                        + " of interface " + type.getName() + ": " + e.getMessage(), e);
            }

        }
    } catch (Exception e) {
        logger.error(e.getMessage(), e);
    }
    return instance;
}

---------------------第三段代码块,华丽丽的分割线------------------------

getAdaptiveExtension的实现原理
public T getAdaptiveExtension() {
    // 获取实例化对象缓存
    Object instance = cachedAdaptiveInstance.get();
    if (instance == null) {
        if (createAdaptiveInstanceError != null) {
            throw new IllegalStateException("Failed to create adaptive instance: " +
                    createAdaptiveInstanceError.toString(),
                    createAdaptiveInstanceError);
        }
        // 双重检查锁后创建自适应扩展
        synchronized (cachedAdaptiveInstance) {
            instance = cachedAdaptiveInstance.get();
            if (instance == null) {
                try {
                    // 创建自适应扩展
                    instance = createAdaptiveExtension();
                    cachedAdaptiveInstance.set(instance);
                } catch (Throwable t) {
                    createAdaptiveInstanceError = t;
                    throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
                }
            }
        }
    }

    return (T) instance;
}
private T createAdaptiveExtension() {
    try {
        // 获取自适应扩展后,注入依赖
        return injectExtension((T) getAdaptiveExtensionClass().newInstance());
    } catch (Exception e) {
        throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
    }
}
private Class<?> getAdaptiveExtensionClass() {
    // 加载全部扩展类
    getExtensionClasses();
    // 加载全部扩展类后,如果有 @Adaptive 标注的类,cachedAdaptiveClass 则一定不会为空
    if (cachedAdaptiveClass != null) {
        return cachedAdaptiveClass;
    }
    // 创建自适应扩展类
    return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
private Class<?> createAdaptiveExtensionClass() {
    // 生成自适应扩展代码
    String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
    // 获取扩展类加载器
    ClassLoader classLoader = findClassLoader();
    // 获取编译器类型的实现类
    org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
    // 编译代码,返回该对象
    return compiler.compile(code, classLoader);
}
getActivateExtension的实现原理
public List<T> getActivateExtension(URL url, String[] values, String group) {
    List<T> activateExtensions = new ArrayList<>();
    List<String> names = values == null ? new ArrayList<>(0) : Arrays.asList(values);
    if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) {
        // 获取所有扩展类
        getExtensionClasses();
        // 遍历所有@Active注解对象
        for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) {
            //spi 扩展名
            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;
            }
            //如果有group匹配
            if (isMatchGroup(group, activateGroup)
                    && !names.contains(name)
                    && !names.contains(REMOVE_VALUE_PREFIX + name)
                    && isActive(activateValue, url)) {
                // 向集合里添加
                activateExtensions.add(getExtension(name));
            }
        }
        // 排序Activate 具体实现在ActivateComparator里,实现了Comparator 接口compare方法
        activateExtensions.sort(ActivateComparator.COMPARATOR);
    }
    List<T> loadedExtensions = 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 (!loadedExtensions.isEmpty()) {
                    activateExtensions.addAll(0, loadedExtensions);
                    loadedExtensions.clear();
                }
            } else {
                //通过扩展名,加载扩展添加到结果集
                loadedExtensions.add(getExtension(name));
            }
        }
    }
    if (!loadedExtensions.isEmpty()) {
        activateExtensions.addAll(loadedExtensions);
    }
    // 返回符合条件的扩展类
    return activateExtensions;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值