美文网首页
dubbo源码1-代理

dubbo源码1-代理

作者: modou1618 | 来源:发表于2018-12-31 09:53 被阅读0次

    一 代理模式

    通过代理对象访问目标对象.可以在代理对象中实现额外功能,增强目标对象。

    静态代理

    动态代理

    jdk代理,基于接口生成,使用反射调用目标对象。
    cglib代理,使用字节码生成继承子类,覆盖重写目标对象方法。不能代理private和final方法
    

    二 dubbo中代理

    dubbo中代理实现为动态代理,分为:基于jdk接口的jdk代理和使用字节码生成方式的javassist代理。

    代理类位置

    2.1ProxyFactory

    代理工厂接口

    2.1.1 <T> T getProxy(Invoker invoker)与<T> T getProxy(Invoker<T> invoker, boolean generic)

     在class ReferenceConfig中解析<dubbo:reference/> 引用服务配置时调用,生成目标接口的代理,作为spring管理的单例bean。
    
     参数invoker则表示dubbo架构中的cluster层对象,通过invoker逐层向下调用,最终通过netty channel发送rpc调用消息。   
    
     generic则表示是否增加通用接口GenericService的的实现,即由服务端和客户端协商确定接口名称,参数等信息,而不是由dubbo基于接口类解析。 
    

    2.1.2 <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url)

     在类ServiceConfig中解析<dubbo:service/>配置时调用,封装接口实现类对象proxy,生成统一的Invoker类型的类对象,提供给下层协议层。
    
     netty server层接收到rpc调用消息后,解析获取消息对应的invoker。
    

    2.2 AbstractProxyFactory

    仅实现了getProxy接口,处理GenericService和EchoService的接口
    
    EchoService是回声服务,由服务端EchoFilter拦截消息并响应返回传输的接口第一个参数。
    

    2.3 jdk代理

    2.3.1 getProxy(Invoker<T> invoker, Class<?>[] interfaces)

        public T getProxy(Invoker invoker, Class[] interfaces) {
            return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces,
                   new InvokerInvocationHandler(invoker));
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            String methodName = method.getName();
            Class<?>[] parameterTypes = method.getParameterTypes();
            if (method.getDeclaringClass() == Object.class) {
                return method.invoke(invoker, args);
            }
            if ("toString".equals(methodName) && parameterTypes.length == 0) {
                return invoker.toString();
            }
            if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
                return invoker.hashCode();
            }
            if ("equals".equals(methodName) && parameterTypes.length == 1) {
                return invoker.equals(args[0]);
            }
            return invoker.invoke(new RpcInvocation(method, args)).recreate();
        }
    

    InvokerInvocationHandler 组装RpcInvocation作为参数调用cluster层invoker.invoke()方法


    rpc请求体结构.png

    2.3.2 getInvoker(T proxy, Class type, URL url)

    public Invoker getInvoker(T proxy, Class type, URL url) {
        return new AbstractProxyInvoker(proxy, type, url) {
            @Override
            protected ObjectdoInvoke(T proxy, String methodName,
                                      Class[] parameterTypes,
                                      Object[] arguments)throws Throwable {
            Method method = proxy.getClass().getMethod(methodName, parameterTypes);
                return method.invoke(proxy, arguments);
            }
        };
    }
    

    通过反射调用目标服务

    2.4 javassist代理

    使用字节码方式生成目标接口代理。如下是对应的字节码处理类

    字节码处理实现类

    2.4.1 getProxy(Invoker<T> invoker, Class<?>[] interfaces)

    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
            return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
    }
    
    getProxy流程图.png

    2.4.2 getInvoker(T proxy, Class type, URL url)

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
            // TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
            final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
            return new AbstractProxyInvoker<T>(proxy, type, url) {
                @Override
                protected Object doInvoke(T proxy, String methodName,
                                          Class<?>[] parameterTypes,
                                          Object[] arguments) throws Throwable {
                    return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
                }
            };
        }
    

    jdk代理中是通鳄梨是过反射的方式实现方法调用,而这里是使用字节码生成Wrapper类对象,而wrapper.invokeMethod是直接调用目标服务的接口。


    getWrapper流程图.png

    相关文章

      网友评论

          本文标题:dubbo源码1-代理

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