dubbo源码分析-回调的实现

来源:互联网 发布:淘宝店海报 编辑:程序博客网 时间:2024/06/05 15:16

这里dubbo的官方文档有一个回调的例子,看看dubbo在内部是如何支持回调的。

CallbackServiceCodec类是用来编码和解码调用方法的参数的,dubbo正是通过判断参数的类型来处理回调的:

private static byte isCallBack(URL url, String methodName ,int argIndex){        //参数callback的规则是 方法名称.参数index(0开始).callback        byte isCallback = CALLBACK_NONE;        if (url != null ) {            String callback = url.getParameter(methodName+"."+argIndex+".callback");            if(callback !=  null) {                if (callback.equalsIgnoreCase("true")) {                     isCallback = CALLBACK_CREATE;                }else if(callback.equalsIgnoreCase("false")){                    isCallback = CALLBACK_DESTROY;                }            }        }        return isCallback;    }
isCallback用来判断参数的类型是否是回调。
public static Object encodeInvocationArgument(Channel channel, RpcInvocation inv, int paraIndex) throws IOException{        //encode时可直接获取url        URL url = inv.getInvoker() == null ? null : inv.getInvoker().getUrl();        byte callbackstatus = isCallBack(url, inv.getMethodName(), paraIndex);        Object[] args = inv.getArguments();        Class<?>[] pts = inv.getParameterTypes();        switch (callbackstatus) {            case CallbackServiceCodec.CALLBACK_NONE:                return args[paraIndex];            case CallbackServiceCodec.CALLBACK_CREATE:                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex , exportOrunexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], true));                return null;            case CallbackServiceCodec.CALLBACK_DESTROY:                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrunexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], false));                return null;            default:                return args[paraIndex];        }    }
可以看到encodeInvocationArgument里面判断参数的类型如果是回调(CALLBACK_CREATE,值为1)的话,会执行exportOrunexportCallbackService,里面会为回调参数对象暴露一个接口:
Invoker<?> invoker = proxyFactory.getInvoker(inst, clazz, exporturl);Exporter<?> exporter = protocol.export(invoker);
ok,客户端把回调接口暴漏出来了。

再来看服务器端:
同样在CallbackServiceCodec类里面:

public static Object decodeInvocationArgument(Channel channel, RpcInvocation inv, Class<?>[] pts, int paraIndex, Object inObject) throws IOException{        // ...        byte callbackstatus = isCallBack(url, inv.getMethodName(), paraIndex);        switch (callbackstatus) {            case CallbackServiceCodec.CALLBACK_NONE:                return inObject;            case CallbackServiceCodec.CALLBACK_CREATE:               return referOrdestroyCallbackService(channel, url, pts[paraIndex], inv, Integer.parseInt(inv.getAttachment(INV_ATT_CALLBACK_KEY + paraIndex)), true);                // ....        }    }
在解析参数时,判断如果是回调参数,那么生成一个代理:

Invoker<?> invoker = new ChannelWrappedInvoker(clazz, channel, referurl, String.valueOf(instid));proxy = proxyFactory.getProxy(invoker);
可以看到根据url生成了一个代理,那么我们实际在调用回调方法的时候,会被传递到客户端去执行客户端的代码。
另外只需要在provider中配置回调参数,这些配置信息会通过registry传递到consumer中。

0 0
原创粉丝点击