Dubbo系列之自适应(Adaptive)拓展点

Dubbo系列之自定义SPI协议拓展点_codain的博客-CSDN博客Dubbo系列之自定义SPI协议拓展点https://blog.csdn.net/qq_38377525/article/details/123002941为了这个文章的内容,大家可以充分吸收,首先要确保大家是了解过上面链接中的章节内容,如果不了解或者不清楚的,个人建议要先搞懂上面的链接,然后再接着看本篇章


自适应(Adaptive)拓展点,简单来说就是能够根据上下文需求动态匹配一个拓展类,调用代码如下

ExtensionLoader.getExtensionLoader(class).getAdaptiveExtension();

自适应拓展点可以通过注解@Adaptive来声明实现,此注解有两种使用方式

1、注册定义在类上面,标识该类为自适应拓展类

@Adaptive
public class MysqlDriver implement Driver{
    //此处代码省略...
}

MysqlDriver在这里就是一个自适应拓展类,通过ExtensionLoader.getExtensionLoader(Driver.class).getAdaptiveExtension();可以返回MysqlDriver类的实例

2、定义在方法上,程序会通过动态代理的方式为其生成一个动态的字节码,进行自适应匹配

@SPI
public interface Driver{
    @Adaptive
    String connection(String name);
}

上述代码意味着存在一个自适应方法,获得一个自适应拓展点代码为:Driver driver=ExtensionLoader.getExtensionLoader(Driver.class).getAdaptiveExtension();


不管@Adaptive是在类上还是方法上,我们都要分析一下源码,看看是怎么实现自适应的,我们从ExtensionLoader.getExtensionLoader(class).getAdaptiveExtension();代码入手

1、getAdaptiveExtension()


public T getAdaptiveExtension() {
        //获取缓存中所有拓展点实例
        Object instance = this.cachedAdaptiveInstance.get();
        if (instance == null) {
            if (this.createAdaptiveInstanceError != null) {
                throw new IllegalStateException("Failed to create adaptive instance: " + this.createAdaptiveInstanceError.toString(), this.createAdaptiveInstanceError);
            }
            //创建自适应拓展点,并缓存
            Holder var2 = this.cachedAdaptiveInstance;
            synchronized(this.cachedAdaptiveInstance) {
                instance = this.cachedAdaptiveInstance.get();
                if (instance == null) {
                    try {
                        //创建自适应拓展点
                        instance = this.createAdaptiveExtension();
                        this.cachedAdaptiveInstance.set(instance);
                    } catch (Throwable var5) {
                        this.createAdaptiveInstanceError = var5;
                        throw new IllegalStateException("Failed to create adaptive instance: " + var5.toString(), var5);
                    }
                }
            }
        }

        return instance;
}

看一下这个代码,是不是和最上面提供的链接逻辑差不多?他存在一个createAdaptiveExtension()方法,这个方法和Dubbo纯SPI的createExtension()方法是一样的逻辑:先获得拓展点实例,再完成依赖注入

2、createAdaptiveExtension()

    private T createAdaptiveExtension() {
        try {
            //下一段代码分析:getAdaptiveExtensionClass()
            return this.injectExtension(this.getAdaptiveExtensionClass().newInstance());
        } catch (Exception var2) {
            throw new IllegalStateException("Can't create adaptive extension " + this.type + ", cause: " + var2.getMessage(), var2);
        }
    }

3、getAdaptiveExtensionClass()

    private Class<?> getAdaptiveExtensionClass() {
        //获取入参的所有拓展点,缓存在一个集合中
        this.getExtensionClasses();
        //如果获取的为null,需要调用createAdaptiveExtensionClass创建
        return this.cachedAdaptiveClass != null ? this.cachedAdaptiveClass : (this.cachedAdaptiveClass = this.createAdaptiveExtensionClass());
    }

4、createAdaptiveExtensionClass()

    private Class<?> createAdaptiveExtensionClass() {
        //返回一个动态拼接的字符串
        String code = (new AdaptiveClassCodeGenerator(this.type, this.cachedDefaultName)).generate();
        ClassLoader classLoader = findClassLoader();
        //获取Conpiler拓展点
        Compiler compiler = (Compiler)getExtensionLoader(Compiler.class).getAdaptiveExtension();
        //动态编译
        return compiler.compile(code, classLoader);
    }

5、调用Dubbo自适应实现类Protocol$Adaptive,采用的是适配器模式,然后根据上下文信息自动适配到相应的协议拓展点来完成服务的加载和发布


附上一个在写这个文章很早之前的一个demo样例链接

 dubbo-spi: dubbo的spi机制讲解https://gitee.com/IT_CB/dubbo-spi/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值