美文网首页
2-3 隐式传参

2-3 隐式传参

作者: xhrg | 来源:发表于2018-12-30 18:46 被阅读0次

应用

先看下dubbo的隐式传参是个什么效果。代码如下所示。

public class PersonServiceImpl implements PersonService {
    public String say(String name) {
        Object obj = RpcContext.getContext().getAttachments();
        System.out.println("获取隐式传参的信息"+obj);
        return name + " say hello ";
    }
}

public class MainClient {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
        PersonService p= applicationContext.getBean(PersonService.class);
        RpcContext.getContext().setAttachment("aaa", "bbb");
        RpcContext.getContext().setAttachment("eee", "ccc");
        System.out.println(p.say("abcd"));
    }
}

上面的代码是服务消费方打印的隐式参数。后面的代码是客户端传递的隐式参数。

服务提供者:

根据之前讲的,我们知道dubbo的服务提供者接受到netty请求,会把参数封装成一个com.alibaba.dubbo.remoting.exchange.Request对象。 该对象有一个属性是Object mData。实际调用的时候,可能会是DecodeableRpcInvocation,该类继承自RpcInvocation。在RpcInvocation中有两个属性。Object[] arguments和Map<String, String> attachments这里的arguments就是函数参数,而attachments就是隐式参数。

Request是请求信息,里面有一个属性是Invocation,同时Invocation的属性也有Request,两者是相互持有的关系。

在dubbo内部函数调用链路中,都是用Invocation在作为函数参数传递。到如下代码的时候,会封装这些隐式参数。

public class ContextFilter implements Filter {
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        Map<String, String> attachments = invocation.getAttachments();
        if (attachments != null) {
            attachments = new HashMap<String, String>(attachments);
            attachments.remove(Constants.PATH_KEY);
            attachments.remove(Constants.GROUP_KEY);
            attachments.remove(Constants.VERSION_KEY);
            attachments.remove(Constants.DUBBO_VERSION_KEY);
            attachments.remove(Constants.TOKEN_KEY);
            attachments.remove(Constants.TIMEOUT_KEY);
        }
        RpcContext.getContext()
                .setInvoker(invoker)
                .setInvocation(invocation)
                //设置隐式参数。
                .setAttachments(attachments)
                .setLocalAddress(invoker.getUrl().getHost(), 
                                 invoker.getUrl().getPort());
        if (invocation instanceof RpcInvocation) {
            ((RpcInvocation)invocation).setInvoker(invoker);
        }
        try {
           //调用前绑定到RpcContext中,调用后在finally去除掉。
            return invoker.invoke(invocation);
        } finally {
            RpcContext.removeContext();
        }
    }
}

而实际上是跟着线程绑定的。

public class RpcContext {
    private static final ThreadLocal<RpcContext> LOCAL = new ThreadLocal<RpcContext>() {
        @Override
        protected RpcContext initialValue() {
            return new RpcContext();
        }
    };
    public static RpcContext getContext() {
        return LOCAL.get();
    }

服务消费者:

消费者和生产者的代码原理是一样的,消费者代码如下:

@Activate(group = Constants.CONSUMER, order = -10000)
public class ConsumerContextFilter implements Filter {
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        RpcContext.getContext()
                .setInvoker(invoker)
                .setInvocation(invocation)
                .setLocalAddress(NetUtils.getLocalHost(), 0)
                .setRemoteAddress(invoker.getUrl().getHost(), 
                                  invoker.getUrl().getPort());
        if (invocation instanceof RpcInvocation) {
            ((RpcInvocation)invocation).setInvoker(invoker);
        }
        try {
            return invoker.invoke(invocation);
        } finally {
            RpcContext.getContext().clearAttachments();
        }
    }
}

相关文章

  • 2-3 隐式传参

    应用 先看下dubbo的隐式传参是个什么效果。代码如下所示。 上面的代码是服务消费方打印的隐式参数。后面的代码是客...

  • SOFABolt 源码分析16 - 上下文机制的设计

    SOFABolt 中存在四种上下文 contextInvokeContext:调用上下文,用于端内隐式传参,并可以...

  • vue路由 filters方法和filter过滤用法总结

    限制单行文字长度 路由传参写法 ---- 声明式 路由传参写法 ---- 编程式 路由传参写法 ---- 路由里要...

  • Python 实例方法、类方法和静态方法

    执行结果: 结论 上面的方法其实本质都是绑定在类上普通方法,只不过Python对不同的方法做了隐式传参@stati...

  • C++隐式类型转换的问题及explicit关键字

    C++隐式类型转换的问题 什么是隐式类型转换? 可以用 单个形参来调用 的构造函数定义了从 形参类型 到 该类类型...

  • golang 数组

    与C数组变量隐式作为指针使用不同,Go数组是值类型,赋值和传参操作都会复制整个数组数据。 func test(x[...

  • 范型

    <:上界 >:下界 <%视图定界 一定要传隐式转换函数 T隐式转换成order[T][T<%M]关系意味着...

  • vue - 路由带参跳转

    vue路由传参按照传参方式可划分为params传参和query传参; params传参分为在url中显示和影藏参数...

  • 8. 汇编-ESP寻址 EBP寻址

    8. 汇编-ESP寻址 EBP寻址 寄存器传参和堆栈传参 寄存器传参 堆栈传参 --ESP寻址 堆栈传参 --EBP寻址

  • Python中的参数传递都有哪些

    大体上分为三种(位置传参和关键字传参以及综合传参)位置传参又包含普通位置传参和序列传参(也是位置传参的一种)关键字...

网友评论

      本文标题:2-3 隐式传参

      本文链接:https://www.haomeiwen.com/subject/rxzvlqtx.html