Dubbo-getExtensionLoader 步骤

33 篇文章 0 订阅

getExtensionLoader 加载过程

  1. 先去缓存中EXTENSION_LOADERS private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64); 加载第一次是空
  2. 创建一个新的放入,value new ExtensionLoader()
  3. new ExtensionLoader构造方法,ExtensionLoader.getExtensionLoader(ExtensionFactory.class)
  4. ExtensionFactory 有一个getExtension,方法,有3个实现实中 AdaptiveExtensionFactory 标注了@Adaptive 进行代理其他的ExtensionFactory
  5. AdaptiveExtensionFactory构造方法,getSupportedExtensions获取支持的扩展类型,SPI,SPRING
  6. getSupportedExtensions获取所有扩展类信息getExtensionClasses
  7. 这里也是也去缓存中加载,没有,双重加锁 loadExtensionClasses,加载成功后入入缓存
  8. loadExtensionClasses加载当前SPI的默认实现。加载这个类的所有扩展点实现,并且按照name和Class对象的形式存储
  9. loadDirectory加载指定文件夹下的文件列表 对其中的文件内容解析并且放入到 extensionClasses Map
  10. loadResource加载资源用于读取文件操作,并且将方法交由 loadClass 来加载类信息
  11. loadClass 最终进行完成类映射

根据name获取扩展点的方法 getExtension

    public T getExtension(String name) {
        if (StringUtils.isEmpty(name)) {
            //名称为空
            throw new IllegalArgumentException("Extension name == null");
        }
        
        if ("true".equals(name)) {
            //加载默认的扩展实现 如果name=true
            //1.getDefaultExtension
            return getDefaultExtension();
        }
        //2.getOrCreateHolder
        //getOrCreateHolder()方法中封装了查找cachedInstances缓存的逻辑
        //获取当前类的holder,实现原理和cachedClasses的方式相同,都是建立同一个引用后再进行加锁
        final Holder<Object> holder = getOrCreateHolder(name);
        Object instance = holder.get();
        //double-check防止并发问题
        if (instance == null) {
            synchronized (holder) {
                instance = holder.get();
                if (instance == null) {
                    //根据扩展名从SPI配置文件中查找对应的扩展实现类
                    //3.根据名称创建扩展实现,放放Holder
                    instance = createExtension(name);
                    holder.set(instance);
                }
            }
        }
        return (T) instance;
    }
  1. getDefaultExtension
  public T getDefaultExtension() {
        //获取扩展类 这里会走最开始的构造流程
        getExtensionClasses();
        if (StringUtils.isBlank(cachedDefaultName) || "true".equals(cachedDefaultName)) {
            return null;
        }
        return getExtension(cachedDefaultName);
    }
  1. getOrCreateHolder

public class Holder<T> {

    private volatile T value;

    public void set(T value) {
        this.value = value;
    }

    public T get() {
        return value;
    }

}

  private Holder<Object> getOrCreateHolder(String name) {
        //根据名称获取实现
        Holder<Object> holder = cachedInstances.get(name);
        if (holder == null) {
            //为空就创建一个放入缓存中
            cachedInstances.putIfAbsent(name, new Holder<>());
            //再获取出来
            holder = cachedInstances.get(name);
        }
        return holder;
    }


  1. createExtension

  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) {
                //没有的话,同样适用putIfAbsent的方式来保证只会创建一个对象并且保存
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            //4. 依赖注入
            // 注入其他扩展点的实体,用于扩展点和其他的扩展点相互打通
            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);
        }
    }

  1. injectExtension
    private T injectExtension(T instance) {
        //检测objectFactory字段
        if (objectFactory == null) {
            return instance;
        }

        try {
            //遍历其中的所有方法
            for (Method method : instance.getClass().getMethods()) {
                //方法遍历判断是否为setter方法  如果不是,忽略该方法继续下一个方法
                if (!isSetter(method)) {
                // 是否是set方法
                // 1. 以"set"开头
                // 2. 参数长度为1
                // 3. 是公开的方法
                    continue;
                }
                /**
                 * Check {@link DisableInject} to see if we need auto injection for this property
                 */
                if (method.getAnnotation(DisableInject.class) != null) {
                    //判断是否禁止注入 如果方法上明确标注了@DisableInject注解,忽略该方法
                    continue;
                }
                //根据setter方法的参数,确定扩展接口
                Class<?> pt = method.getParameterTypes()[0];
                //判断是否为基本类型 原始类型(boolean、char、byte、short、int、long、float、double)
                //如果参数为简单类型,忽略该setter方法(略)
                if (ReflectUtils.isPrimitives(pt)) {
                    continue;
                }

                try {
                    //setter方法注入 获取需要set的扩展点名称
                    String property = getSetterProperty(method);
                    //从扩展中获取对象 加载并实例化扩展实现类
                    Object object = objectFactory.getExtension(pt, property);
                    //从ExtensionLoader中加载指定的扩展点
                     比如有一个方法为setRandom(LoadBalance loadBalance),那么则以为着需要加载负载均衡中名为random的扩展点
                    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;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值