dubbo源码(三)-Adaptive使用

前言

前面两篇文章对dubbo SPI的使用和原理进行简单的讲解,大家应该对dubbo SPI有了认识。在 Dubbo 中,很多拓展都是通过 SPI 机制进行加载的,比如 Protocol、Cluster、LoadBalance 等。

现在我们再来回顾一下dubbo SPI的简单使用,代码如下:

        // 1、先获取 extensionLoader
        ExtensionLoader<Robot> extensionLoader = ExtensionLoader.getExtensionLoader(Robot.class);
        // 2、根据名称获取对应的扩展点instance
        Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
        // 3、调用对应扩展点instance的方法
        optimusPrime.sayHello();       

这段代码演示了dubbo SPI的使用,但是有一个问题,扩展点对应的实现类不能在程序运行时动态指定,就是extensionLoader.getExtension方法写死了扩展点对应的实现类,不能在程序运行期间根据运行时参数进行动态改变。

对于这个矛盾的问题,就有引入我们今天要将的Adaptive,就是dubbo 的自适应机制。Dubbo 通过自适应拓展机制很好的解决了。我们首先看一下如果是我们,怎么解决这个矛盾,下面给出示例:

  1. 这里先定义一个接口,取名叫AdaptiveExt, 这里需要加一个com.alibaba.dubbo.common.extension.SPI的注解
@SPI
public interface AdaptiveExt {

    String echo(String msg, URL url);
}

这里的URL类为dubbo里面的URL

  1. 接着创建一个实现类SpringAdaptiveExtImpl,按照dubbo SPI 配置,配置好
public class SpringAdaptiveExtImpl implements AdaptiveExt {

    @Override
    public String echo(String msg, URL url) {
        return "spring";
    }
}
  1. 重点来了,这一步我们解决扩展点对应的实现类不能在程序运行时动态指定的问题,这里我们自己编写一个AdaptiveExt自适应实现类,如下:
public class AdaptiveExtProxy implements AdaptiveExt{

    @Override
    public String echo(String msg, URL url) {
        // 非空检查
        if (url == null) {
            throw new IllegalArgumentException("url == null");
        }

        // 1、从 URL 中获取 AdaptiveExt 名称
        String name = url.getParameter("adaptive.ext");
        if (name == null ) {
            throw new IllegalArgumentException("name == null");
        }

        // 2、调用 SPI 动态加载具体的 AdaptiveExt
        AdaptiveExt adaptiveExt = ExtensionLoader
                .getExtensionLoader(AdaptiveExt.class)
                .getExtension(name);

        // 3、调用具体的方法
        return adaptiveExt.echo(msg, url);
    }
}

AdaptiveExtProxy其实是一个代理类,AdaptiveExtProxy所代理的对象是在echo方法中通过SPI加载得到的,echo方法主要做了三件事情:

  • 从 URL 中获取 AdaptiveExt 名称
  • 通过 SPI 加载具体的 AdaptiveExt 实现类
  • 调用目标方法
  1. 进行测试,测试代码如下:
    @Test
    public void test() {
        URL url = URL.valueOf("test://localhost/test?adaptive.ext=spring");
        AdaptiveExt adaptiveExt = new AdaptiveExtProxy();
        System.out.println(adaptiveExt.echo("e", url));
    }

输出结果:

spring
Process finished with exit code 0

到这里,我们自己基本上解决了上面所说的矛盾。大家大致知道 dubbo SPI 扩展点对应的实现类,在程序运行期间根据运行时参数进行动态改变的解决方案了。就是设置一个代理类,代理类根据程序运行期间URL的参数,动态加载响应的实现类并代理。

dubbo Adaptive的使用

刚才我们简单讲了dubbo的自适应拓展机制是啥,现在我们开学习dubbo 自适应机制的学习。dubbo 自适应机制的使用是通过注解的方式,注解为com.alibaba.dubbo.common.extension.Adaptive。直接上代码示例:

  1. 首先定义一个接口,名称为AdaptiveExt,使用SPIAdaptive修饰:
@SPI
public interface AdaptiveExt {

    @Adaptive
    String echo(String msg, URL url);
}
  1. 创建三个实现类,分别为DubboAdaptiveExtImplSpringAdaptiveExtImplSpringBootAdaptiveExtImpl
public class DubboAdaptiveExtImpl implements AdaptiveExt {

    @Override
    public String echo(String msg, URL url) {
        return "dubbo";
    }
}
public class SpringAdaptiveExtImpl implements AdaptiveExt {

    @Override
    public String echo(String msg, URL url) {
        return "spring";
    }
}
public class SpringBootAdaptiveExtImpl implements AdaptiveExt{

    @Override
    public String echo(String msg, URL url) {
        return "spring boot";
    }
}
  1. 接着在META-INF/dubbo文件夹下创建一个文件,名称为Robot的全限定名com.hui.wang.dubbo.learn.dubbo.adaptive.AdaptiveExt,内容如下:
dubbo=com.hui.wang.dubbo.learn.dubbo.adaptive.DubboAdaptiveExtImpl
spring=com.hui.wang.dubbo.learn.dubbo.adaptive.SpringAdaptiveExtImpl
springboot=com.hui.wang.dubbo.learn.dubbo.adaptive.SpringBootAdaptiveExtImpl

到这里,示例的基本代码搭建完成,现在开始进入使用和测试

  1. 在URL里面指定参数,代码为:
@Test
    public void test1() {
        ExtensionLoader<AdaptiveExt> extExtensionLoader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);
        AdaptiveExt adaptiveExt = extExtensionLoader.getAdaptiveExtension();
        URL url = URL.valueOf("test://localhost/test?adaptive.ext=spring");
        System.out.println(adaptiveExt.echo("d", url));
    }

打印结果为:

spring

可以看出,当URL中参数指定相应的扩展点实现类名称后,就可以根据名称动态的调用响应名称的实现类。

  1. 配置Adaptive注解的value值,代码如下:
@SPI
public interface AdaptiveExt {

    @Adaptive(value = {"myAdaptiveName"})
    String echo(String msg, URL url);
}

测试代码:

    @Test
    public void test4() {
        ExtensionLoader<AdaptiveExt> extExtensionLoader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);
        AdaptiveExt adaptiveExt = extExtensionLoader.getAdaptiveExtension();
        URL url = URL.valueOf("test://localhost/test?myAdaptiveName=spring");
        System.out.println(adaptiveExt.echo("d", url));
    }

打印结果为:

spring

在方法上打上@Adaptive注解,注解中的value与链接中的参数的key一致,链接中的key对应的value就是spi中的name,获取相应的实现类。
3.@Adaptive注解使用在实现类上,代码如下:

@Adaptive
public class DubboAdaptiveExtImpl implements AdaptiveExt {

    @Override
    public String echo(String msg, URL url) {
        return "dubbo";
    }
}

测试代码:

    @Test
    public void test4() {
        ExtensionLoader<AdaptiveExt> extExtensionLoader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class);
        AdaptiveExt adaptiveExt = extExtensionLoader.getAdaptiveExtension();
        URL url = URL.valueOf("test://localhost/test?myAdaptiveName=spring");
        System.out.println(adaptiveExt.echo("d", url));
    }

打印结果为:

dubbo

这里可以看到实现类上有@Adaptive注解后,默认调用该类进行调用。

到这里基本上就是dubbo 自适应机制的使用,即@Adaptive注解的使用,在下一篇我们将介绍@Adaptive注解背后的源码实现

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,784评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,745评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,702评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,229评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,245评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,376评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,798评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,471评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,655评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,485评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,535评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,235评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,793评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,863评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,096评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,654评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,233评论 2 341

推荐阅读更多精彩内容