Dubbo服務暴露過程當中有涉及到調用ProxyFactory 中方法獲取Invoker對象的過程,如今咱們來深究下源碼,來看下這個過程是在作些什麼,返回的Invoker 對象是什麼,咱們來看一下代碼的切入點:java
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
這裏proxyFactory實在ServiceConfig中定義的靜態常量,賦值後沒法修改:express
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
proxyFactory經過ExtensionLoader拓展機制進行加載。查看ProxyFactory接口源碼以下:apache
/* * Copyright 1999-2011 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.dubbo.rpc; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.extension.Adaptive; import com.alibaba.dubbo.common.extension.SPI; /** * ProxyFactory. (API/SPI, Singleton, ThreadSafe) * * @author william.liangf */ @SPI("javassist") public interface ProxyFactory { /** * create proxy. * * @param invoker * @return proxy */ @Adaptive({Constants.PROXY_KEY}) <T> T getProxy(Invoker<T> invoker) throws RpcException; /** * create invoker. * * @param <T> * @param proxy * @param type * @param url * @return invoker */ @Adaptive({Constants.PROXY_KEY}) <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException; }
ProxyFactory接口有三個實現類,分別爲JavassistProxyFactory、JdkProxyFactory、StubProxyFactoryWrapper。其中JavassistProxyFactory、JdkProxyFactory做爲代理工廠,StubProxyFactoryWrapper實現了對代理工廠進行裝飾的功能。在Dubbo中經過SPI配置默認的代理工廠爲JavassistProxyFactoryapp
接下來咱們重點來看JavassistProxyFactory 代理工廠:less
繼承圖以下:jvm
JavassistProxyFactory 源碼很是簡單,只有兩個方法:(代碼調試的入參已經註釋在源碼中)ide
/* * Copyright 1999-2011 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.dubbo.rpc.proxy.javassist; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.bytecode.Proxy; import com.alibaba.dubbo.common.bytecode.Wrapper; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory; import com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker; import com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler; /** * JavaassistRpcProxyFactory * * @author william.liangf */ public class JavassistProxyFactory extends AbstractProxyFactory { @SuppressWarnings("unchecked") public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) { return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker)); } /** * * @param proxy DemoServiceImpl * @param type interface com.alibaba.dubbo.demo.DemoService * @param url injvm://127.0.0.1/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&default.accepts=1000&default.threadpool=fixed&default.threads=100&default.timeout=5000&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&owner=uce&pid=9176&side=provider×tamp=1527927801444 * @param <T> * @return */ public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) { // TODO Wrapper類不能正確處理帶$的類名 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); } }; } }
其中getProxy是實現抽象類AbstractProxyFactory中的抽象方法。AbstractProxyFactory抽象類實現了ProxyFactory接口中getProxy方法,JdkProxyFactory也實現了抽象類AbstractProxyFactory中的getProxy抽象方法。Javassist與Jdk動態代理的共同部分被封裝在父類AbstractProxyFactory中,具體的實現類只需負責實現代理生成過程的差別化部分。ui
其中getInvoker方法是在ProxyFactory接口中定義的,用於建立Invoker。getInvoker中代碼很簡單,直接返回一個匿名類。匿名類繼承了AbstractProxyInvoker抽象類,AbstractProxyInvoker抽象類又實現了Invoker接口,即代表該匿名類實現了Invoker接口,匿名類是封裝了服務提供者的調用者。this
Invoker接口定義了一個泛型。定義的方法很簡單,只有兩個方法,以下:url
package com.alibaba.dubbo.rpc; import com.alibaba.dubbo.common.Node; public interface Invoker<T> extends Node { //獲取服務對象接口 Class<T> getInterface(); //獲取封裝了服務的調用者 Result invoke(Invocation invocation) throws RpcException; }
抽象類AbstractProxyInvoker實現了Invoker接口,AbstractProxyInvoker定義屬性和構造方法以下:
private final T proxy; private final Class<T> type; private final URL url; public AbstractProxyInvoker(T proxy, Class<T> type, URL url) { if (proxy == null) { throw new IllegalArgumentException("proxy == null"); } if (type == null) { throw new IllegalArgumentException("interface == null"); } if (!type.isInstance(proxy)) { throw new IllegalArgumentException(proxy.getClass().getName() + " not implement interface " + type); } this.proxy = proxy; this.type = type; this.url = url; }
AbstractProxyInvoker也實現了invoker方法。方法內部很簡單,直接經過RpcResult建立一個對象便可,建立RpcResult時的構建參數是經過方法doInvoke生成的。以下:
public Result invoke(Invocation invocation) throws RpcException { try { return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments())); } catch (InvocationTargetException e) { return new RpcResult(e.getTargetException()); } catch (Throwable e) { throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e); } }
這裏的doInvoke方法是抽象方法,由子類實現。抽象方法定義以下:
protected abstract Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable;
在ProxyFactory接口JavassistProxyFactory實現類中,getInvoker方法內部經過匿名內部類實現了doInvoke抽象方法。
Result接口主要定義了RPC 調用的相關方法,以下:
package com.alibaba.dubbo.rpc; import java.util.Map; public interface Result { Object getValue(); Throwable getException(); boolean hasException(); Object recreate() throws Throwable; @Deprecated Object getResult(); Map<String, String> getAttachments(); String getAttachment(String key); String getAttachment(String key, String defaultValue); }
RpcResult是對Result接口的一個實現。可看做對傳入對象Object的一個包裝,部分源碼以下:
public class RpcResult implements Result, Serializable { private static final long serialVersionUID = -6925924956850004727L; private Object result; private Throwable exception; private Map<String, String> attachments = new HashMap<String, String>(); public RpcResult() { } public RpcResult(Object result) { this.result = result; } public RpcResult(Throwable exception) { this.exception = exception; } public Object recreate() throws Throwable { if (exception != null) { throw exception; } return result; } }
這就是Dubbo服務發佈的Invoker生成過程