博客
关于我
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/

你可能感兴趣的文章
ObsoleteAttribute 可适用于除程序集、模块、参数或返回值以外的所有程序元素。 将元素标记为过时可以通知用户:该元素在产品的未来版本中将被移除。...
查看>>
OC Xcode快捷键
查看>>
oc 中的.m和.mm文件区别
查看>>
OC 内存管理黄金法则
查看>>
oc57--Category 分类
查看>>
occi库在oracle官网的下载针对vs2008
查看>>
OceanBase 安装使用详细说明
查看>>
OceanBase详解及如何通过MySQL的lib库进行连接
查看>>
OCP题库升级,新版的052考试题及答案整理-18
查看>>
OCR使用总结
查看>>
OfficeWeb365 SaveDraw 文件上传漏洞复现
查看>>
office中的所有content type
查看>>
office之Excel 你会用 Ctrl + E 吗?
查看>>
Office办公软件里的“开发工具”选项卡-ChatGPT4o作答
查看>>
OGG初始化之使用数据库实用程序加载数据
查看>>
ogg参数解析
查看>>
ognl详解
查看>>
Ogre 插件系统
查看>>
Oil Deposits
查看>>
oj2894(贝尔曼福特模板)
查看>>