博客
关于我
Dubbo 源码分析 - Dubbo SPI 获取自适应扩展点实例
阅读量:484 次
发布时间:2019-03-06

本文共 3881 字,大约阅读时间需要 12 分钟。

Dubbo SPI 系列文章:扩展点的自适应实现

在上一篇文章中,我们分析了 Dubbo SPI 中 Expansion Point 的实现,特别关注 ExtensionLoader 如何通过 getExtension(String name) 方法获取扩展点实现类对象。本文将深入探讨 Dubbo 源码中的 getAdaptiveExtension() 方法,以及它如何支持自适应扩展点的实例化和注入。


正文

1. ExtensionLoader 部分属性

在 ExtensionLoader 中,与扩展相关的实例缓存和实现类缓存是关键组件。以下是代码中定义的相关部分:

// 自适应扩展点实例缓存private final Holder< Object > cachedAdaptiveInstance = new Holder<>();// 自适应扩展点实现类的类加载类别private volatile Class> cachedAdaptiveClass = null;

缓存机制显著提升了扩展点的性能表现,减少了重复计算和资源浪费。


2. ExtensionLoader#getAdaptiveExtension()

要获取自适应扩展点实例,ExtensionLoader 提供了 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);        }                // 通过锁同步机制确保 thread-safety        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;}

3. ExtensionLoader#createAdaptiveExtension()

自适应扩展点的实例化涉及以下步骤:

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

4. getAdaptiveExtensionClass

与上一篇文章类似,getAdaptiveExtensionClass() 方法负责获取合适的扩展点实现类:

private Class> getAdaptiveExtensionClass() {    // 加载已存在的实现类    getExtensionClasses();        if (cachedAdaptiveClass != null) {        return cachedAdaptiveClass;    }        //ync动态编译生成新实现类    return cachedAdaptiveClass = createAdaptiveExtensionClass();}

5. createAdaptiveExtensionClass

为了支持动态编译,createAdaptiveExtensionClass() 会生成自适应扩展点的实现类:

private Class> createAdaptiveExtensionClass() {    // 使用自定义编译工具生成插件    String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();    ClassLoader classLoader = findClassLoader();    org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(Compiler.class).getAdaptiveExtension();    return compiler.compile(code, classLoader);}

生成的代码实现会自动引用所需扩展点,以支持灵活配置和注入。


6. injectExtension

最后,injectExtension() 方法负责注入所需的扩展点实例:

private T injectExtension(T instance) {    if (objectFactory == null) {        return instance;    }        // 通过反射检查并注入属性    for (Method method : instance.getClass().getMethods()) {        if (!isSetter(method)) {            continue;        }                if (method.getAnnotation(DisableInject.class) != null) {            continue;        }                Class pt = method.getParameterTypes()[0];        if (ReflectUtils.isPrimitives(pt)) {            continue;        }                try {            // 从对象工厂获取相关扩展实例            Object object = objectFactory.getExtension(pt, getProperty());            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);        }    }        return instance;}

总结

通过在 ExtensionLoader 中实现 cache 算法和动态编译机制,Dubbo 为自适应扩展点提供了高度的灵活性和性能优化。缓存显著减少了重复计算,动态编译支持了扩展点的灵活继承。这种设计理念不仅提升了扩展点的性能表现,还为开发者提供了更强大的灵活性和可编程性。

转载地址:http://ugpdz.baihongyu.com/

你可能感兴趣的文章
Nginx的使用总结(一)
查看>>
Nginx的可视化神器nginx-gui的下载配置和使用
查看>>
Nginx的是什么?干什么用的?
查看>>
Nginx访问控制_登陆权限的控制(http_auth_basic_module)
查看>>
nginx负载均衡器处理session共享的几种方法(转)
查看>>
nginx负载均衡的5种策略(转载)
查看>>
nginx负载均衡的五种算法
查看>>
Nginx运维与实战(二)-Https配置
查看>>
Nginx配置ssl实现https
查看>>
Nginx配置TCP代理指南
查看>>
Nginx配置——不记录指定文件类型日志
查看>>
Nginx配置代理解决本地html进行ajax请求接口跨域问题
查看>>
Nginx配置参数中文说明
查看>>
Nginx配置好ssl,但$_SERVER[‘HTTPS‘]取不到值
查看>>
Nginx配置实例-负载均衡实例:平均访问多台服务器
查看>>
NIFI大数据进阶_连接与关系_设置数据流负载均衡_设置背压_设置展现弯曲_介绍以及实际操作---大数据之Nifi工作笔记0027
查看>>
NIO ByteBuffer实现原理
查看>>
Nio ByteBuffer组件读写指针切换原理与常用方法
查看>>
NIO Selector实现原理
查看>>
nio 中channel和buffer的基本使用
查看>>