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

你可能感兴趣的文章
Oracle 表
查看>>
oracle 课堂笔记
查看>>
Oracle 返回结果集的 存储过程
查看>>
Oracle 递归
查看>>
Oracle 递归函数与拼接
查看>>
oracle 逻辑优化,提升高度,综合SQL上下文进行逻辑优化
查看>>
oracle 闪回关闭,关闭闪回即disable flashback的操作步骤
查看>>
oracle 限制用户并行,insert /*parallel */ 到不同用户,并行起不来的问题
查看>>
oracle--用户,权限,角色的管理
查看>>
Oracle-定时任务-JOB
查看>>
oracle.dataaccess 连接池,asp.net使用Oracle.DataAccess.dll连接Oracle
查看>>
oracle00205报错,Oracle控制文件损坏报错场景
查看>>
Oracle10g EM乱码之快速解决
查看>>
Oracle10g下载地址--多平台下的32位和64位
查看>>
Oracle10g安装了11g的ODAC后,PL/SQL连接提示TNS:无法解析指定的连接标识符
查看>>
oracle11g dataguard物理备库搭建(关闭主库cp数据文件到备库)
查看>>
Oracle11G基本操作
查看>>
Oracle11g服务详细介绍及哪些服务是必须开启的?
查看>>
Oracle11g静默安装dbca,netca报错处理--直接跟换操作系统
查看>>
oracle12安装软件后安装数据库,然后需要自己配置监听
查看>>