2019独角兽企业重金招聘Python工程师标准>>>

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> 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配置默认的代理工厂为JavassistProxyFactory

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

继承图如下:

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> 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&timestamp=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) {@Overrideprotected 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<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;}
  • 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;@DeprecatedObject 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生成过程

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

Dubbo服务服务暴露之ProxyFactory Invoker相关推荐

  1. Dubbo学习记录(十六)--服务调用【二】 - Invoker的调用、ProxyFactory、Protocol、Filter,Exchanger, Transporter扩展点

    服务调用的前置学习[二] 服务调用涉及到的东西比较多, 需要一个个的理解透彻, 最终才能串起来: 服务端DubboInvoker的包装 DubboInvoker的生成是在服务导出的过程中创建的:由于D ...

  2. 阿里面试官:你知道Dubbo的服务暴露机制么?

    点赞再看,养成习惯,微信搜一搜[三太子敖丙]关注这个喜欢写情怀的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系 ...

  3. 深入解析 Dubbo 3.0 服务端暴露全流程

    简介:随着云原生时代的到来,Dubbo 3.0 的一个很重要的目标就是全面拥抱云原生.正因如此,Dubbo 3.0 为了能够更好的适配云原生,将原来的接口级服务发现机制演进为应用级服务发现机制. 作者 ...

  4. Dubbo服务端暴露全流程

    本文来说下Dubbo服务端暴露全流程 文章目录 概述 什么是应用级服务发现 服务端暴露全流程 暴露injvm协议的服务 注册service-discovery-registry协议 暴露Triple协 ...

  5. Dubbo服务端服务发布(一)Invoker创建

    在Dubbo的服务发布过程中,Invoker的构造是一个重要的步骤,Invoker代表的是一个可以调用的服务的接口.它的定义如下: public interface Invoker<T> ...

  6. dubbo源码分析7 之 服务本地暴露

    在上一篇文章我们分析了一下 dubbo 在服务暴露发生了哪些事,今天我们就来分析一下整个服务暴露中的本地暴露.(PS:其实我感觉本地暴露蛮鸡肋的).本地暴露需要服务提供方与服务消费方在同一个 JVM. ...

  7. Dubbo之服务导入流程解析

    Dubbo之服务导入流程解析 接着上回<Dubbo之服务暴露流程浅析>,上一篇文章已经介绍完了Dubbo的服务提供者的服务暴露的整个流程,本文主要介绍Dubbo服务消费者的服务导入流程. ...

  8. Dubbo笔记 ⑤ : 服务发布流程 - Protocol#export

    文章目录 一.前言 二.RegistryProtocol#export 1. URL解析 1.1 获取注册中心URL 1.2 获取服务URL 1.3 获取订阅URL 2. 服务暴露 3. 服务注册 4 ...

  9. Dubbo笔记 ㉘ : 服务自省-消费者

    文章目录 一.前言 二.ReferenceAnnotationBeanPostProcessor#doGetInjectedBean 1. newProxyInstance 2. ReferenceB ...

  10. Dubbo笔记 ㉗ : 服务自省-提供者

    文章目录 一.前言 1. 概念 二.服务自省 1. 相关配置 3.1 dubbo.application.metadata-type 3.2 dubbo.application.register-co ...

最新文章

  1. noip2019集训测试赛(五)
  2. android 图片气泡,android图片上显示气泡消息
  3. golang reflect
  4. 大学生动漫网页设计模板 机动战士高达静态网页制作成品下载 HTML漫画网页作业带JS轮播图
  5. java数组有顺序吗_java – 使用特定顺序对(数组)列表进行排序
  6. JAVA 数据类型数组
  7. 常见的几种 RuntimeException
  8. python—列表,元组,字典
  9. 正在发生的景象--从大众消费到圈层经济
  10. 简易支付系统的架构设计
  11. Google浏览器升级为最新打开网页时缓慢 “正在建立安全连接..........”解决方法
  12. Windows 10简单搭建一个局域网Web下载分享界面
  13. 3D资产大掌柜—Connecter
  14. 强世功:中美“关键十年” ——“新罗马帝国”与“新的伟大斗争”
  15. 刷题体验第一天——《录鼎记》第一章
  16. HarmonyOS实现点亮LED
  17. Java --- JVM动态链接与方法调用
  18. 深入学习理解Java集合
  19. [译]Unity3D Shader教程(二)HLSL
  20. ubuntu 下myeclipse下载,安装,破解

热门文章

  1. Adopt Open JDK官方文档(八)OpenJDK 项目介绍
  2. 68.TextView设置中划线、下划线
  3. 演示:扩展ACL的配置与应用技巧
  4. jsonp多次请求报错 not a function的解决方法
  5. VS2010与.NET4系列 10. VS2010代码智能感知增强
  6. cocos2d-x学习笔记10:动作3:补间动作
  7. java获取取得Timestamp类型的当前系统时间
  8. 路由子系统之fib相关结构体
  9. Ceph 撸源码系列(二):Ceph源代码里的那些锁 std::mutex(2 of 3)
  10. echart 地图 某个地区_「省份」Echart系列 | 绘制世界地图含中国各个省份(地图篇)(一) - seo实验室...