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

你可能感兴趣的文章
nodejs系列之express
查看>>
nodejs系列之Koa2
查看>>
Nodejs连接mysql
查看>>
nodejs连接mysql
查看>>
NodeJs连接Oracle数据库
查看>>
nodejs配置express服务器,运行自动打开浏览器
查看>>
Nodemon 深入解析与使用
查看>>
node不是内部命令时配置node环境变量
查看>>
node中fs模块之文件操作
查看>>
Node中同步与异步的方式读取文件
查看>>
Node中的Http模块和Url模块的使用
查看>>
Node中自启动工具supervisor的使用
查看>>
Node入门之创建第一个HelloNode
查看>>
node全局对象 文件系统
查看>>
Node出错导致运行崩溃的解决方案
查看>>
Node响应中文时解决乱码问题
查看>>
node基础(二)_模块以及处理乱码问题
查看>>
node安装及配置之windows版
查看>>
Node实现小爬虫
查看>>
Node提示:error code Z_BUF_ERROR,error error -5,error zlib:unexpected end of file
查看>>