博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Dubbo服务服务暴露之ProxyFactory Invoker
阅读量:6228 次
发布时间:2019-06-21

本文共 8013 字,大约阅读时间需要 26 分钟。

hot3.png

Dubbo服务暴露过程中有涉及到调用ProxyFactory 中方法获取Invoker对象的过程,现在我们来深究下源码,来看下这个过程是在做些什么,返回的Invoker 对象是什么,我们来看一下代码的切入点:

Invoker
invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);

这里proxyFactory实在ServiceConfig中定义的静态常量,赋值后无法修改:

private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();

proxyFactory通过ExtensionLoader拓展机制进行加载。查看ProxyFactory接口源码如下:

/* * 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 getProxy(Invoker
invoker) throws RpcException; /** * create invoker. * * @param
* @param proxy * @param type * @param url * @return invoker */ @Adaptive({Constants.PROXY_KEY})
Invoker
getInvoker(T proxy, Class
type, URL url) throws RpcException;}

ProxyFactory接口有三个实现类,分别为JavassistProxyFactory、JdkProxyFactory、StubProxyFactoryWrapper。其中JavassistProxyFactory、JdkProxyFactory作为代理工厂,StubProxyFactoryWrapper实现了对代理工厂进行装饰的功能。在Dubbo中通过SPI配置默认的代理工厂为JavassistProxyFactory

接下来我们重点来看JavassistProxyFactory 代理工厂:

继承图如下:1f144b5dcbad3f4d8997620c5862a1b794a.jpg

JavassistProxyFactory 源码非常简单,只有两个方法:(代码调试的入参已经注释在源码中)

/* * 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 getProxy(Invoker
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&timestamp=1527927801444 * @param
* @return */ public
Invoker
getInvoker(T proxy, Class
type, URL url) { // TODO Wrapper类不能正确处理带$的类名 final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type); return new AbstractProxyInvoker
(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中,具体的实现类只需负责实现代理生成过程的差异化部分。

其中getInvoker方法是在ProxyFactory接口中定义的,用于创建Invoker。getInvoker中代码很简单,直接返回一个匿名类。匿名类继承了AbstractProxyInvoker抽象类,AbstractProxyInvoker抽象类又实现了Invoker接口,即表明该匿名类实现了Invoker接口,匿名类是封装了服务提供者的调用者。

Invoker接口定义了一个泛型。定义的方法很简单,只有两个方法,如下:

package com.alibaba.dubbo.rpc;import com.alibaba.dubbo.common.Node;public interface Invoker
extends Node { //获取服务对象接口 Class
getInterface(); //获取封装了服务的调用者 Result invoke(Invocation invocation) throws RpcException;}

抽象类AbstractProxyInvoker实现了Invoker接口,AbstractProxyInvoker定义属性和构造方法如下:

private final T proxy;    private final Class
type; private final URL url; public AbstractProxyInvoker(T proxy, Class
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; }
  • proxy:是final类型变量,指向服务提供者
  • type:是final类型变量,服务的接口类型
  • url:是final类型变量,携带服务地址、端口等多种信息的自定义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
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
attachments = new HashMap
(); 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生成过程

 

转载于:https://my.oschina.net/LucasZhu/blog/1833087

你可能感兴趣的文章
动态规划复习-HDU1231
查看>>
串门赛: NOIP2016模拟赛——By Marvolo 丢脸记
查看>>
Webapck项目开发基本构建及配置
查看>>
poj2562
查看>>
用matplotlib绘制图像
查看>>
flex 整理 笔记
查看>>
Cocos2d-x之瓦片地图 Tiled
查看>>
对网卡中断绑定的脚本
查看>>
Android第二次作业
查看>>
Trie
查看>>
(Joomla)多功能健康模块
查看>>
基于CC2530的zigbee信道、PANID扫描设备
查看>>
前端基础之jquery
查看>>
You are beautiful
查看>>
GIS部分理论知识备忘随笔
查看>>
应用安装和卸载
查看>>
CSS深入理解学习笔记之border
查看>>
查找并替换中文字符
查看>>
GRU(Gated Recurrent Unit) 更新过程推导及简单代码实现
查看>>
inline和宏之间的区别
查看>>