美文网首页
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