由Dubbo回声测试学到的

来源:互联网 发布:volatile java 优缺点 编辑:程序博客网 时间:2024/05/01 01:39
摘要: 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 {@Overridepublic 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;}@Overridepublic 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);}}

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

原创粉丝点击