dubbo爲consumer建立代理

ReferenceConfig.init()方法中獲取到了最終的代理對象,先觀察一下代理對象的視圖。java

默認使用javassist生成動態類,可配置proxy爲jdk,則使用jdk動態代理:app

<dubbo:reference id="hello" interface="com.zhang.HelloService" proxy="jdk" merger="true" check="false"/>

jdk代理對象視圖以下圖:ide

RegistryDirectory中有一個 urlInvokerMap。ui

// Map<url, Invoker> cache service url to invoker mapping.
private volatile Map<String, Invoker<T>> urlInvokerMap;

示例:this

鍵: dubbo://192.168.233.6:20880/com.zhang.HelloService?anyhost=true&application=consumerk_app&check=false&dubbo=2.5.2&group=a&interface=com.zhang.HelloService&iothreads=2&merger=true&methods=sayHello,sayException,sayHi,sayFuck&pid=6736&sayException.retries=0&sayFuck.retries=0&sayFuck.return=true&sayHello.retries=0&sayHi.retries=0&side=consumer&timeout=6000&timestamp=1516256748120
值: com.alibaba.dubbo.registry.integration.RegistryDirectory$InvokerDelegete@4147e2b6url

而後分析代理的建立過程,主要的調用棧以下:spa

貼出Protocol$Adpative的代碼:代理

package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
    public void destroy() {
        throw new UnsupportedOperationException(
                "method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
    }

    public int getDefaultPort() {
        throw new UnsupportedOperationException(
                "method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
    }

    public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0,
            com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {
        if (arg1 == null)
            throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg1;
        //url不一樣,得到的擴展名是不同的
        String extName = (url.getProtocol() == null ? "dubbo" : url
                .getProtocol());
        if (extName == null)
            throw new IllegalStateException(
                    "Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
                            + url.toString() + ") use keys([protocol])");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
                .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
                .getExtension(extName);
        return extension.refer(arg0, arg1);
    }

    public com.alibaba.dubbo.rpc.Exporter export(
            com.alibaba.dubbo.rpc.Invoker arg0)
            throws com.alibaba.dubbo.rpc.Invoker {
        if (arg0 == null)
            throw new IllegalArgumentException(
                    "com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException(
                    "com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = (url.getProtocol() == null ? "dubbo" : url
                .getProtocol());
        if (extName == null)
            throw new IllegalStateException(
                    "Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
                            + url.toString() + ") use keys([protocol])");
        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
                .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
                .getExtension(extName);
        return extension.export(arg0);
    }
}

從調用棧能夠看到,Protocol\$Adpative.refer(Class, URL)調用了2次。可是傳遞的URL參數是不同的,code

第一次獲取的protocol是 ProtocolFilterWrapper/ProtocolListenerWrapper/RegistryProtocol,
第二次獲取的protocol是 ProtocolFilterWrapper/ProtocolListenerWrapper/DubboProtocol。對象

因此在ProtocolListenerWrapper和ProtocolFilterWrapper中走的分支不一樣。
(第一次的URL是:
registry://192.168.153.1:2181/com.alibaba.dubbo.registry.RegistryService?application=consumer&dubbo=2.1.2&localhost=true&pid=2504&refer=application%3Dconsumer%26dubbo%3D2.1.2%26interface%3Dcom.zhang.HelloService%26methods%3DsayHello%26pid%3D2504%26timestamp%3D1516461886484&registry=zookeeper&timestamp=1516461886531
Protocol$Adpative.refer的refer方法中,getExtension()返回的擴展是ProtocolListenerWrapper/ProtocolFilterWrapper/RegistryProtocol。
第二次的URL是:
dubbo://192.168.153.1:20880/com.zhang.HelloService?anyhost=true&application=consumer&check=false&dubbo=2.1.2&interface=com.zhang.HelloService&methods=sayHello&pid=2504&timestamp=1516461886484)

 

//ProtocolListenerWrapper類
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
    if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
        //先進這個分支
        return protocol.refer(type, url);
    }
    //後續再進這個分支
    return new ListenerInvokerWrapper<T>(protocol.refer(type, url), 
            Collections.unmodifiableList(
                    ExtensionLoader.getExtensionLoader(InvokerListener.class)
                    .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
}

//ProtocolFilterWrapper類
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
    if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
        //先進這個分支
        return protocol.refer(type, url);
    }
    //後續再進這個分支
    return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}

 

ReferenceConfig<T>的createProxy方法負責建立代理,分析以後獲得的步驟大體以下:

1. 生成invoker

// ReferenceConfig.createProxy方法。refprotocol是Protocol$Adpative對象
invoker = refprotocol.refer(interfaceClass, url);

    1.1 生成filter鏈(使用內部類把filter和next封裝起來。至關於建立一個類,有Filter屬性,和Invoker屬性)

//ProtocolFilterWrapper類
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
    Invoker<T> last = invoker;
// ConsumerContextFilter, MonitorFilter, FutureFilter List
<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group); if (filters.size() > 0) { for (int i = filters.size() - 1; i >= 0; i --) { final Filter filter = filters.get(i); final Invoker<T> next = last; last = new Invoker<T>() { public Class<T> getInterface() { return invoker.getInterface(); } public URL getUrl() { return invoker.getUrl(); } public boolean isAvailable() { return invoker.isAvailable(); } public Result invoke(Invocation invocation) throws RpcException { return filter.invoke(next, invocation); } public void destroy() { invoker.destroy(); } @Override public String toString() { return invoker.toString(); } }; } } return last; }

    1.2 生成RegistryDirectory$InvokerDelegete對象

// RegistryDirectory.toInvokers
// protocol.refer(serviceType, url)就是調用Protocol$Adpative的refer方法,即遞歸調用
invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);

    1.3 生成MockClusterInvoker。涉及2個類:Protocol$Adpative和Cluster$Adpative,調用棧以下,

package com.alibaba.dubbo.rpc.cluster;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Cluster$Adpative implements com.alibaba.dubbo.rpc.cluster.Cluster {
    public com.alibaba.dubbo.rpc.Invoker join(
            com.alibaba.dubbo.rpc.cluster.Directory arg0)
            throws com.alibaba.dubbo.rpc.cluster.Directory {
        if (arg0 == null)
            throw new IllegalArgumentException(
                    "com.alibaba.dubbo.rpc.cluster.Directory argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException(
                    "com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("cluster", "failover");
        if (extName == null)
            throw new IllegalStateException(
                    "Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url("
                            + url.toString() + ") use keys([cluster])");
        com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster) ExtensionLoader
                .getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class)
                .getExtension(extName);
        // extension是MockClusterWrapper
        return extension.join(arg0);
    }
}


2. 建立代理。

private static final ProxyFactory proxyFactory = 
        ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
private T createProxy(Map<String, String> map) {
    // 省略其餘代碼
    return (T) proxyFactory.getProxy(invoker);
}

/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.ProxyFactory文件內容:

stub=com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
jdk=com.alibaba.dubbo.rpc.proxy.jdk.JdkProxyFactory
javassist=com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory

能夠看到上面有一個wrapper,因此調用getExtension方法得到的擴展是StubProxyFactoryWrapper

動態生成的ProxyFactory$Adpative類代碼,格式化以下:

package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class ProxyFactory$Adpative implements com.alibaba.dubbo.rpc.ProxyFactory {
    public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0)
            throws com.alibaba.dubbo.rpc.Invoker {
        if (arg0 == null)
            throw new IllegalArgumentException(
                    "com.alibaba.dubbo.rpc.Invoker argument == null");
        if (arg0.getUrl() == null)
            throw new IllegalArgumentException(
                    "com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
        com.alibaba.dubbo.common.URL url = arg0.getUrl();
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException(
                    "Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
                            + url.toString() + ") use keys([proxy])");
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
                .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class)
                .getExtension(extName);
        // extension實際上是StubProxyFactoryWrapper對象,對JavassistProxyFactory作一個wrap
        return extension.getProxy(arg0);
    }

    public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0,
            java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2)
            throws java.lang.Object {
        if (arg2 == null)
            throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg2;
        String extName = url.getParameter("proxy", "javassist");
        if (extName == null)
            throw new IllegalStateException(
                    "Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
                            + url.toString() + ") use keys([proxy])");
        com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
                .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class)
                .getExtension(extName);
        return extension.getInvoker(arg0, arg1, arg2);
    }
}

 因此getExtension的返回對象是:StubProxyFactoryWrapper/JavassistProxyFactory

// JavassistProxyFactory
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
//1、 Proxy p = Proxy.getProxy(interfaces); //2、 p.newInstance(new InvokerInvocationHandler(invoker)); return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); }

Proxy0和proxy0是javassist動態生成的類:其中p是Proxy0實例,調用newInstance(InvocationHandler)方法建立proxy0實例。

下面是推測的代碼(大概):

class com.alibaba.dubbo.common.bytecode.Proxy0 extends com.alibaba.dubbo.common.bytecode.Proxy {
    public Object newInstance(java.lang.reflect.InvocationHandler h){
        return new com.alibaba.dubbo.common.bytecode.proxy0($1);
    }
}

class com.alibaba.dubbo.common.bytecode.proxy0 implements
    com.alibaba.dubbo.rpc.service.EchoService, com.zhang.HelloService {
    public <init>(java.lang.reflect.InvocationHandler arg0){
        handler=$1;
    }
    public static java.lang.reflect.Method[] methods;
    private java.lang.reflect.InvocationHandler handler;
    
    public java.lang.String sayHello(){
        Object[] args = new Object[0];
        Object ret = handler.invoke(this, methods[0], args);
        return (java.lang.String)ret;
    }
    public java.lang.Object $echo(java.lang.Object arg0){
        Object[] args = new Object[1];
        args[0] = ($w)$1;
        Object ret = handler.invoke(this, methods[1], args);
        return (java.lang.Object)ret;
    }
}
相關文章
相關標籤/搜索