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生成过程