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×tamp=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®istry=zookeeper×tamp=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×tamp=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; } }