Dubbo源码分析之ExtensionLoader原理

ExtensionLoader是dubbo实现SPI的核心类。ExtentionLoader的逻辑入口可以分为getExtension、getAdaptiveExtension、getActivateExtension三个。分别是普通扩展类、自适应扩展类、和激活扩展类。

1. getExtension实现原理

方法逻辑:先通过参数name判断是否为true,不为true再通过#createExtension方法获取扩展点实例然后把它放入缓存。

public T getExtension(String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalArgumentException("Extension name == null");
        }
        //name=true
        if ("true".equals(name)) {
            return getDefaultExtension(); //默认扩展点
        }
        Holder<Object> holder = getOrCreateHolder(name);
        Object instance = holder.get();
        if (instance == null) {
            synchronized (holder) {
                instance = holder.get();
                if (instance == null) {
                    //获取Protocol对应的实例
                    instance = createExtension(name);
                    //把Protocol的实例放到缓存里面
                    holder.set(instance);
                }
            }
        }
        return (T) instance;
 }

createExtension方法:先获取扩展点对应的实现类,调用#getExtensionClasses方法。这个方法,会查找指定目录 /META-INF/dubbo || /META-INF/services 下对应的 type->也就是本次演示案例的 Protocol properties 文件,然后扫描这个文 件下的所有配置信息。然后保存到一个 HashMap 中(classes),key=name(对应 protocol 文件中配置的 protocol), value=对 应配置的类的实例。然后从缓存中获取扩展实例,如果为null则放入缓存中。接着进行依赖属性注入,获取包装扩展对象。

//创建扩展名对应的扩展实例
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);
            // 创建 Wrapper 拓展对象
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (CollectionUtils.isNotEmpty(wrapperClasses)) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                    type + ") couldn't be instantiated: " + t.getMessage(), t);
        }
}

//获取扩展点对应的实现类,先从缓存中获取,没有则从配置文件中加载
private Map<String, Class<?>> getExtensionClasses() {
        // 从缓存中,获得拓展实现类数组
        Map<String, Class<?>> classes = cachedClasses.get();
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                if (classes == null) {
                    // 从配置文件中,加载拓展实现类数组
                    classes = loadExtensionClasses();
                    // 设置到缓存中
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
}
#injectExtension注入依赖属性:遍历类中的方法,方法以set开头,含有一个参数并且满足public修饰。符合条件的通过参数类型从ExtensionFactory获取实例,然后把实例注入进去。
private T injectExtension(T instance) {
        try {
            if (objectFactory != null) {
                for (Method method : instance.getClass().getMethods()) {
                    //判断方法是否以set开头,只有一个参数并且用public修饰
                    if (isSetter(method)) {
                        /**
                         * 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 {
                            String property = getSetterProperty(method);
                            //从ExtensionFactory中获取实例
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                //调用 set 方法进行赋值
                                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;
}

2. getAdaptiveExtension实现原理

在#getAdaptiveExtension方法中,会给扩展点接口自动生成实现类的字符串,然后通过编译器将实现类字符串编译为自适应类并返回。在实现类上可以看到有@Adaptive注解。实现类字符串生成主要逻辑总结如下:

(1) 生成package、import、类名称等头部信息。此处只会引入一个ExtensionClassLoader,为了不写import其他类,其他方法调用时全部使用全路径。类名为:接口名$Adaptive。

(2) 遍历接口所有方法,获取方法的返回类型、参数类型、异常类型等。为(3)判断是否为空做准备。

(3) 生成参数为空校验代码,如果有远程调用还会加上Invocation参数为空的校验。

(4) 生成默认实现类名称。

(5) 生成获取扩展点名称的代码。根据@Adaptive注解中配置的key值生成不同的获取代码。

(6) 生成获取具体扩展实现类代码,最终还是通过getExtension(extName)方法获取自适应扩展类的真正实现。

//获取自适应扩展点    
public T getAdaptiveExtension() {
        // 从缓存中,获得自适应拓展对象
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
            //如果之前创建没报错
            if (createAdaptiveInstanceError == null) {
                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);
                        }
                    }
                }
            } else {
                throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
            }
        }

        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);
        }
}

3. getActivateExtension实现原理

 

public List<T> 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);

}


public List<T> getActivateExtension(URL url, String[] values, String group) {
        List<T> exts = new ArrayList<>();
        List<String> names = values == null ? new ArrayList<>(0) : Arrays.asList(values);
        if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) {
            // 获得拓展实现类数组
            getExtensionClasses();
            for (Map.Entry<String, Object> 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)// 判断是否配置移除。例如 <dubbo:service filter="-monitor" />,则 MonitorFilter 会被移除
                            && isActive(activateValue, url)) {// 判断是否激活
                        exts.add(ext);
                    }
                }
            }
            exts.sort(ActivateComparator.COMPARATOR);
        }
        List<T> 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;
}

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值