7.2-dubbo源码阅读之-ExtensionLoader

概述

ExtensionLoader 在dubbo中是一个很重要的类,其实也是一个工具类,根据名字我们知道就是复杂扩展点加载,我们也知道dubbo是微内核,良好的扩展机制,主要是依赖ExtendsionLoader

构造方法说起

就一个构造方法

  1. type 就是对应接口的Class, 由于dubbo使用缓存,一个接口对应一个ExtensionLoader
  2. extensionDirector 是ExtensionLoader 访问器
  3. scopeModel 是dubbo3 开始引入的新概念,Model方便一些数据的管理先忽略

    ExtensionLoader(Class<?> type, ExtensionDirector extensionDirector, ScopeModel scopeModel) {
        //当前扩展加载器,需要加载的扩展的类型
        this.type = type;
        //创建扩展加载器的扩展访问器对象
        this.extensionDirector = extensionDirector;
        //从扩展访问器中获取扩展执行前后的回调器
        this.extensionPostProcessors = extensionDirector.getExtensionPostProcessors();
        //创建实例化对象的策略对象
        initInstantiationStrategy();
        //如果当前扩展类型为扩展注入器类型则设置当前注入器变量为空,否则的话获取一个扩展注入器扩展对象
        //1)这里有个type为空的判断,普通的扩展类型肯定不是ExtensionInjector类型 这里必定会为每个非扩展注入ExtensionInjector类型创建一个ExtensionInjector类型的扩展对象,
//2) 这里代码会走extensionDirector.getExtensionLoader(ExtensionInjector.class)这一步进去之后的代码刚刚看过就不再看了,这个代码会创建一个为ExtensionInjector扩展对象的加载器对象ExtensionLoader
//3) getAdaptiveExtension() 这个方法就是通过扩展加载器获取具体的扩展对象的方法我们会详细说
        this.injector = (type == ExtensionInjector.class ?
            null :
            extensionDirector.getExtensionLoader(ExtensionInjector.class).getAdaptiveExtension());
        //创建Activate注解的排序器
        this.activateComparator = new ActivateComparator(extensionDirector);
        //为扩展加载器下的域模型对象赋值
        this.scopeModel = scopeModel;
    }

下面分别介绍几个主要的

extensionPostProcessors 后置处理器

这个后置处理器在bean实例后使用
this.extensionPostProcessors = extensionDirector.getExtensionPostProcessors();

初始化实例策略

initInstantiationStrategy();

ExtensionInjector 完成ioc 中的set注入

这个如果不是很明白的参考。 dubbo源码之-ExtensionInjector
this.injector = (type == ExtensionInjector.class ?
null :
extensionDirector.getExtensionLoader(ExtensionInjector.class).getAdaptiveExtension());

此出有一个getAdaptiveExtension 方法 参考 获取扩展点实现

获取扩展点实现类

getExtensionClasses 加载普通的扩展点

// 加载扩展类 返回 key name value Class map 类型数据结构
    private Map<String, Class<?>> getExtensionClasses() {
        Map<String, Class<?>> classes = cachedClasses.get();
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                if (classes == null) {
                    try {
                        //加载扩展类型
                        classes = loadExtensionClasses();
                    } catch (InterruptedException e) {
                        logger.error(COMMON_ERROR_LOAD_EXTENSION, "", "",
                            "Exception occurred when loading extension class (interface: " + type + ")",
                            e);
                        throw new IllegalStateException(
                            "Exception occurred when loading extension class (interface: " + type + ")",
                            e);
                    }
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }

主要 loadExtensionClasses 方法这个参考 《dubbo源码阅读之-dubbo-spi机制中的配置文件都可以存放再哪个路径下》

这里总结重点:
1.简单说就是获取@SPI接口下面有几个实现类
2.cachedAdaptiveClass 中缓存@Adaptive类,并且一个type下只能有一个带有注解@Adaptive的实现类,否则抛异常
3.cachedActivates 中缓存@Activate注解的类,一个name下只能存在一个,使用覆盖的策略
4.普通的扩展点实现,如果没写key的情况下
使用类的简名-接口简名 做为name

getAdaptiveExtensionClass 加载自适应的扩展点

getAdaptiveExtensionClass
/**
     * 获取自适应扩展实现类
     * @return
     */
    private Class<?> getAdaptiveExtensionClass() {
        //获取扩展类型,将扩展类型存入成员变量cachedClasses中进行缓存
        getExtensionClasses();
        //在上个方法的详细解析中的最后一步loadClass方法中如果扩展类型存在Adaptive注解将会将扩展类型赋值给
        // cachedAdaptiveClass,否则的话会把扩展类型都缓存起来存储在扩展集合extensionClasses中
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        //扩展实现类型没有一个这个自适应注解Adaptive时候,会走到这里
        //刚刚我们扫描到了扩展类型然后将其存入cachedClasses集合中了 接下来我们看下如何创建扩展类型
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }

说明:
1.如果一个类实现存在Adaptive注解的实现类型之间获取相关的实现类型
2. 如果没有使用 createAdaptiveExtensionClass 创建一个代理

创建Adaptive代理类

dubbo 自己写了一个代码生成类和编译类我们先不再深入讲解

获取扩展点实例

dubbo的写法风格: 我们调用的方法往往就是以下路子不再每个单独分析:
1.缓存获取,如果有就返回
2.如果缓存中没有,经过双重检查后调用创建方法
3.创建内容存在相应的缓存中

getAdaptiveExtension 获取自适应扩展点实例

public T getAdaptiveExtension() {
	.......
	instance = createAdaptiveExtension();
	........
}
private T createAdaptiveExtension() {
        try {
            //获取扩展类型实现类, 创建扩展对象 AdaptiveExtensionInjector
            T instance = (T) getAdaptiveExtensionClass().newInstance();
            //注入扩展对象之前的回调方法
            instance = postProcessBeforeInitialization(instance, null);
            //注入扩展对象 set方法注入
            injectExtension(instance);
            //注入扩展对象之后的回调方法
            instance = postProcessAfterInitialization(instance, null);
            //初始化扩展对象的属性,如果当前扩展实例的类型实现了Lifecycle则调用当前扩展对象的生命周期回调方法initialize()(来自Lifecycle接口)
            //参考样例第一个instance为ExtensionInjector的自适应扩展对象类型为AdaptiveExtensionInjector,
            // 自适应扩展注入器(适配器)用来查询具体支持的扩展注入器比如scope,spi,spring注入器
            initExtension(instance);
            return instance;
        } catch (Exception e) {
            throw new IllegalStateException(
                "Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }

在这里插入图片描述

getExtension 获取扩展点实例

private T createExtension(String name, boolean wrap) {
        // 1.扩展的创建的第一步扫描所有jar中的扩展实现,这里扫描完之后获取对应扩展名字的扩展实现类型的Class对象
        //getExtensionClasses 获得map key: name value: class
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null || unacceptableExceptions.contains(name)) {
            //出现异常了 转换下异常信息 再抛出
            throw findException(name);
        }
        try {
            T instance = (T) extensionInstances.get(clazz);
            if (instance == null) {
                //第一次获取缓存中肯定没有则创建扩展对象然后缓存起来
                //2. createExtensionInstance 这个是与自适应扩展对象创建对象的不同之处
                extensionInstances.putIfAbsent(clazz, createExtensionInstance(clazz));
                instance = (T) extensionInstances.get(clazz);
                //注入之前 前置处理
                instance = postProcessBeforeInitialization(instance, name);
                //注入扩展自适应方法,这个方法前面讲自适应扩展时候说了,注入自适应扩展方法的自适应扩展对象
                injectExtension(instance);
                //注入之前 后置处理
                instance = postProcessAfterInitialization(instance, name);
            }
            //是否开启了wrap
            //Dubbo通过Wrapper实现AOP的方法
            if (wrap) {
                //这个可以参考下Dubbo扩展的加载
                List<Class<?>> wrapperClassesList = new ArrayList<>();
                //wrap类型排序 这个wrap类型是如何来的呢,
                // 在前面扫描扩展类型的时候如果当前扩展类型不是Adaptive注解修饰的,
                // 并且当前类型type有个构造器参数是type自身的也是前面加载扩展类型时候说的装饰器模式
                // 可以参考DubboProtocol的构造器
                if (cachedWrapperClasses != null) {
                    wrapperClassesList.addAll(cachedWrapperClasses);
                    //根据Wrapper注解的order值来进行排序值越小越在列表的前面
                    wrapperClassesList.sort(WrapperComparator.COMPARATOR);
                    //反转之后值越大就会在列表的前面
                    Collections.reverse(wrapperClassesList);
                }
                //从缓存中查到了wrapper扩展则遍历这些wrapp扩展进行筛选
                if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
                    for (Class<?> wrapperClass : wrapperClassesList) {
                        Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
                        //需要包装的扩展名。当此数组为空时,默认值为匹配
                        //看下当前扩展是否匹配这个wrap,如何判断呢?
                        //wrapper注解不存在或者matches匹配,或者mismatches不包含当前扩展
                        //如果匹配到了当前扩展对象是需要进行wrapp的就为当前扩展创建当前wrapper扩展对象进行包装
                        boolean match = (wrapper == null) || ((ArrayUtils.isEmpty(
                            wrapper.matches()) || ArrayUtils.contains(wrapper.matches(),
                            name)) && !ArrayUtils.contains(wrapper.mismatches(), name));
                        //这是扩展类型是匹配wrapp的则开始注入
                        if (match) {
                            //匹配到了就创建所有的wrapper类型的对象同时构造器参数设置为当前类型
                            instance = injectExtension(
                                (T) wrapperClass.getConstructor(type).newInstance(instance));
                            instance = postProcessAfterInitialization(instance, name);
                        }
                    }
                }
            }

            // Warning: After an instance of Lifecycle is wrapped by cachedWrapperClasses, it may not still be Lifecycle instance, this application may not invoke the lifecycle.initialize hook.
            //初始化扩展,如果当前扩展是Lifecycle类型则调用初始化方法
            initExtension(instance);
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException(
                "Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(),
                t);
        }
    }

在这里插入图片描述

小结

普通的扩展点获取实例和 AdaptiveExtension(自适应) 区别:

  1. 自适应的 创建实例直接使用 newInstance, 普通使用 InstantiationStrategy 创建实例
  2. 自适应扩展点,不处理包装类,set 注入功能 Wrapper

getActivateExtensions 获取Activate扩展点实例

从文件加载中我们知道cachedActivates 存放被@Activate注解修饰的类

public List<T> getActivateExtensions() {
        checkDestroyed();
        List<T> activateExtensions = new ArrayList<>();
        TreeMap<Class<?>, T> activateExtensionsMap = new TreeMap<>(activateComparator);
        getExtensionClasses();
        for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) {
            String name = entry.getKey();
            Object activate = entry.getValue();
            if (!(activate instanceof Activate)) {
                continue;
            }
            activateExtensionsMap.put(getExtensionClass(name), getExtension(name));
        }
        if (!activateExtensionsMap.isEmpty()) {
            activateExtensions.addAll(activateExtensionsMap.values());
        }

        return activateExtensions;
    }

getActivateExtensions 获取思路比较简单: 直接调用的
getExtension(name);
步骤:

  1. 首先加载所有的实现类getExtensionClasses();
  2. 判断是否存在 Activate注解
  3. getExtension(name) 直接获取,如果存在多个 并且进行覆盖, 按照ActivateComparator的规则排序
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值