dubbo源码分析-回调的实现

这里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中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值