由Dubbo回声测试学到的

摘要: Dubbo中的回声测试是如何实现的?为什么能将任意的服务引用都强制转为EchoService?来看看吧,欢迎指正

最近在看Dubbo的用户手册,看到了回声测试一小节的说明如下,请注意图片中的红框中的部分:

红色部分说:只需要将任意服务引用强制转换为EchoService,即可使用。

看到这里我想起了java中关于强制转换的一个限制:必须有继承关系,就是说两个类之间要能够进行类型转换,必须有继承关系才可以。 可是很明显,我们写的Dubbo服务接口是与EchoService接口没有任何集成关系的,这是如何实现的呢?

带着这个问题,去群里问了一下群主,群主给了如下截图:

1、

2、

3、

4、


可以看到,Dubbo在为我们写的服务创建动态代理的时候,是在传入的接口中人为的增加了“EchoService.class”接口的,也就是说,通过创建动态代理的时候向接口中增加一个接口,来保证强制转换的合法性。

这样就解决了强制转换的问题,但是又一个问题来了,EchoService接口中的方法是怎么实现的呢?因为我们写的接口是没有实现这个接口的,所以EchoService接口类中定义的方法也必然没有实现,虽然通过动态代理让我们的实现类实现了这个接口,但实际运行的时候还是会报错。

EchoService是这样定义的:


很奇怪的是,这里面的方法名字是写成了 $echo 的形式。

这个方法我们没有实现,那么如何保证在执行的时候能够执行呢?这是因为Dubbo提供了很多Filter,针对这个EchoService提供了一个EchoFilter实现:

可以看到,在方法里,直接判断当前执行的方法是不是$echo,如果是,则直接将参数返回,结束执行过程,否则继续执行后面的Filter。

为了验证一下,我也写了一点代码:

首先,也有一个EchoService接口,与Dubbo的一模一样。

public interface EchoService {
Object $echo(Object message);
}

然后自己定义了一个MyService接口和它的一个实现类MyServiceImpl。

接口类:

public interface MyService {
public void sayHello();
}

实现类:

public class MyServiceImpl implements MyService {
@Override
public void sayHello() {
System.out.println("MyServiceImpl:hello");
}
}

我要实现的功能是,将我的MyService实例对象转为EchoService对象 ,并调用其$echo方法。

运行代码如下:

public static void main(String[] args) {
//首先定义一个MyService实例
MyService myservice = new MyServiceImpl();
//获取该实例所实现的接口
Class<?>[] interfaces2 = myservice.getClass().getInterfaces();
//将EchoService接口添加到Class<?>数组中
Class<?>[] interfaces = new Class<?>[interfaces2.length + 1];
interfaces[0] = EchoService.class;
for (int i = 0; i < interfaces2.length; i++) {
interfaces[i + 1] = interfaces2[i];
}
//创建代理对象
Object obj = Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(), interfaces, new MyInvocationHandler(
myservice));
//正常调用
MyService ms = (MyService) obj;
ms.sayHello();
//强制转为EchoServic对象并调用方法
EchoService ec = (EchoService) obj;
Object data = ec.$echo("aaaaa");
System.out.println(data);
}

注意,我实现了一个MyInvocationHandler:这个类是java动态代理必须的。

public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println(method.getName());
//处理EchoService方法,从而实现回声定位功能
if(method.getName().equals("$echo")){
return args[0];
}
return method.invoke(target, args);
}
}

运行一下,发现没有问题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值