深入了解Dubbo SPI 工作机制——@Adaptive(6)

文章详细介绍了Dubbo的SPI机制,特别是@Adaptive注解的作用。@Adaptive用于动态选择最佳的实现类,可以根据接口方法上的注解或者URL参数来决定调用哪个实现。在接口和方法上使用@Adaptive,Dubbo会生成静态代理类,根据URL信息动态调用相应的实现。虽然这种方式提供了灵活性,但可能会增加代码的复杂性。
摘要由CSDN通过智能技术生成

@Adaptive这个注解就是适配策略,我都是称呼为最佳适配子类,或者最佳适配类。就是找到最佳的子实现类的,其实就是默认的类。这个注解可以打在类上方,那么dubbo SPI机制通过接口获取实例类,就是获取到有@Adaptive注解的实现类。

接口:

package com.enjoy.service;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.Adaptive;
import com.alibaba.dubbo.common.extension.SPI;

import java.rmi.RemoteException;
import java.util.Map;

/**
 * SPI 全称为 Service Provider Interface,是一种服务发现机制,目标是为接口寻找实现类。
 * Java SPI 的作法:
 * 		1.在类路径下META-INF/service下创建文件,名称为接口的全限定名。
 * 		2.将接口实现类的全限定名配置在文件中
 * 		3.服务启动时,将由服务加载器读取配置文件,并加载实现类。
 *
 * Dubbo SPI的作法:
 * 		1.Dubbo 增强原生的SPI机制来更好的满足拓展要求,其以键值对的方式对接口的实现进行配置管理。
 * 		2.Dubbo引入三个注解: SPI、Adaptive和Activate。
 *
 * 	只有标注了SPI注解的接口,才是Dubbo的菜
 */
@SPI("b")
public interface InfoService {
	Object sayHello(String name) ;
	//@Adaptive
	Object passInfo(String msg, URL url) ;
}

实现类 InfoServiceAImpl:

package com.enjoy.infoService.impl;


import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.Activate;
import com.enjoy.service.InfoService;

public class InfoServiceAImpl implements InfoService {

    @Override
    public Object sayHello(String name) {
        System.out.println(name+",你好,调通了A实现!");
        return name+",你好,调通了A实现!";
    }

    @Override
    public Object passInfo(String msg, URL url) {
        System.out.println("恭喜你,调通了A实现");
        return msg;
    }

}

实现类InfoServiceBImpl

package com.enjoy.infoService.impl;


import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.Activate;
import com.enjoy.service.InfoService;

public class InfoServiceBImpl implements InfoService {

    @Override
    public Object sayHello(String name) {
        System.out.println(name+",你好,调通了B实现!");
        return name+",你好,调通了B实现!";
    }

    @Override
    public Object passInfo(String msg, URL url) {
        System.out.println("恭喜你,调通了B实现");
        return msg;
    }

}

实现类InfoServiceCImpl

package com.enjoy.infoService.impl;


import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.common.extension.Adaptive;
import com.enjoy.service.InfoService;

@Adaptive
public class InfoServiceCImpl implements InfoService {

    @Override
    public Object sayHello(String name) {
        System.out.println(name+",你好,调通了C实现!");
        return name+",你好,调通了C实现!";
    }

    @Override
    public Object passInfo(String msg, URL url) {
        System.out.println("恭喜你,调通了C实现");
        return msg;
    }

}

测试:

case1:类上有@Adaptive注解,那么调用这个接口的方法,就会调用@Adaptive注解类的方法

 

case 2: @Adaptive也可以在接口中打在具体的方法上,然后根据URL传递的key选择具体的实现类,很灵活

 

注释掉之前的实现类C:

测试:

 

 需要说明的是 test://localhost/test?info.service=a.  info.service就是接口名InfoService的驼峰,还需要用 . 将各个单词拆分。当然我们也可以直接在接口中,给@Adaptive定义个名称,然后URL也需要修改

接口定义:

测试case中URL也需要修改:

 

至此,@Adaptive的功能演示完毕。

源码分析

那么,它是如何做到这样的功能的呢? 还是看源码,加载 ExtensionLoader 的流程是一样的,不懂可以看上一篇深入了解Dubbo SPI 工作机制——@Activate (5)_chen_yao_kerr的博客-CSDN博客

下面全是debug的流程:

1:

 

2:

 

我们看到步骤3中得到一个String code,而这个code就是我们拼接出来的一个静态代理类,它负责根据URL中的key调用具体的业务实现类。下面我拷贝出来它拼写的类:

通过代码确认,我们可以知道实际上我们获取到的是静态代理类

 

而最后一步,就是调用静态代理类的拼接好了的业务方法,整个流程就走通了。

 

个人觉得,这种适配的方式可以动态的根据URL选择具体的实现类,很灵活。但是,老是需要在方法中定义URL,这样静态代理类才能够根据Dubbo的适配方式去选择具体的实现类,写起来有点累赘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值