Dubbo官网对Invoker进行了说明:

Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。

在服务提供方,Invoker 用于调用服务提供类。在服务消费方,Invoker 用于执行远程调用。Invoker 是由 Protocol 实现类构建而来。

服务提供者的Invoker的创建过程

在服务发布ServiceConfig的export方法中,最后发布的实际上是一个经过增强的Invoker对象,下面具体分析一下Invoker的创建逻辑。

    // 通过动态代理转换成InvokerInvoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);// 服务发布Exporter<?> exporter = protocol.export(wrapperInvoker);

上面代码中的PROXY_FACTORY实际上是ProxyFactory的自适应扩展点:

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

默认是由javassist实现,每个方法都由@Adaptive注解修饰。

因此调用getInvoker方法时,会创建一个ProxyFactory$Adaptive动态代理类。

@SPI("javassist")
public interface ProxyFactory {/*** create proxy.** @param invoker* @return proxy*/@Adaptive({PROXY_KEY})<T> T getProxy(Invoker<T> invoker) throws RpcException;/*** create proxy.** @param invoker* @return proxy*/@Adaptive({PROXY_KEY})<T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException;/*** create invoker.** @param <T>* @param proxy* @param type* @param url* @return invoker*/@Adaptive({PROXY_KEY})<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;}

ProxyFactory$Adaptive

通过下面生成的代码可以看到,getInvoker方法会找到extName为javassist的静态扩展点,该扩展点的实现可以在SPI配置文org.apache.dubbo.rpc.ProxyFactory中得到,即:javassist=org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory

public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory {public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {if (arg0 == null)throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");if (arg0.getUrl() == null)throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");org.apache.dubbo.common.URL url = arg0.getUrl();String extName = url.getParameter("proxy", "javassist");if (extName == null)throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString()+ ") use keys([proxy])");org.apache.dubbo.rpc.ProxyFactory extension =(org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);return extension.getProxy(arg0);}public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0, boolean arg1) throws org.apache.dubbo.rpc.RpcException {if (arg0 == null)throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");if (arg0.getUrl() == null)throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");org.apache.dubbo.common.URL url = arg0.getUrl();String extName = url.getParameter("proxy", "javassist");if (extName == null)throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString()+ ") use keys([proxy])");org.apache.dubbo.rpc.ProxyFactory extension =(org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);return extension.getProxy(arg0, arg1);}public org.apache.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, org.apache.dubbo.common.URL arg2) throws org.apache.dubbo.rpc.RpcException {if (arg2 == null)throw new IllegalArgumentException("url == null");org.apache.dubbo.common.URL url = arg2;String extName = url.getParameter("proxy", "javassist");if (extName == null)throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString()+ ") use keys([proxy])");org.apache.dubbo.rpc.ProxyFactory extension =(org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class).getExtension(extName);return extension.getInvoker(arg0, arg1, arg2);}
}

JavassistProxyFactory.getInvoker

javassist是一个动态生成代码的类库,用来实现动态代理。

proxy:目标接口的真实实现

type:目标接口

url:协议地址

JavassistProxyFactory 创建了一个继承自 AbstractProxyInvoker 类的匿名对象,并覆写了抽象方法 doInvoke。覆写后的 doInvoke 逻辑比较简单,仅是将调用请求转发给了 Wrapper 类的 invokeMethod 方法。Wrapper 用于“包裹”目标类,最终还是会通过invokeMethod方法反射调用目标方法。

    @Overridepublic <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {// TODO Wrapper cannot handle this scenario correctly: the classname contains '$'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);}};}

Dubbo Invoker相关推荐

  1. 源码分析Dubbo Invoker概述----服务发现、集群、负载均衡、路由体系

    Invoker,负载网络调用组件,底层依懒与网络通信,Invoker主要负责服务调用,自然与路由(比如集群)等功能息息相关,本节先从整体上把控一下Dubbo服务调用体系,服务发现.集群.负载均衡.路由 ...

  2. 自己实现Dubbo Invoker

    1.Dubbo Invoker 用来执行spring注入的业务接口的实现类的方法.下面我来自己实现一套.基本上是dubbo的设计模式思想. 2.先看下使用说明: //User 对象 class Use ...

  3. dubbo源码实践-protocol层-invoker理解

    1概述 Invoker官方解释: Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实 现 ...

  4. 源码解读Dubbo分层设计思想

    I作者:vivo互联网服务器团队-Wang Genfu 一.Dubbo分层整体设计概述 我们先从下图开始简单介绍Dubbo分层设计概念: (引用自Duboo开发指南-框架设计文档) 如图描述Dubbo ...

  5. Dubbo Cloud Native 实践与思考

    Dubbo Cloud Native 实践与思考 分享简介 Cloud Native 应用架构随着云技术的发展受到业界特别重视和关注,尤其是 CNCF(Cloud Native Computing F ...

  6. Dubbo Cloud Native 之路的实践与思考

    Dubbo Cloud Native 实践与思考 Dubbo Cloud Native 实践与思考 分享简介 自我介绍 主要议程 Cloud Native 基础设施 服务发现(Service Disc ...

  7. Dubbo消费者代理的创建

    在消费者端,dubbo通过AnnotationBean类实现了BeanPostProcessor接口用来对beanFactory的中bean进行相应的处理. 关于消费者的bean以及bean中@Ref ...

  8. 源码分析Dubbo服务消费端启动流程

    通过前面文章详解,我们知道Dubbo服务消费者标签dubbo:reference最终会在Spring容器中创建一个对应的ReferenceBean实例,而ReferenceBean实现了Spring生 ...

  9. Soul 网关源码阅读(四)Dubbo请求概览

    Soul 网关源码阅读(四)Dubbo请求概览 简介     本次启动一个dubbo服务示例,初步探索Soul网关源码的Dubbo请求处理流程 示例运行 环境配置     在Soul源码clone下来 ...

最新文章

  1. 解决myeclipse中新建javaweb工程,无法使用Web App Libraries问题
  2. 线性表的表示和实现方式之链式表示和实现
  3. HTML 5新元素和CSS
  4. C++ Primer 5th笔记(chap 16 模板和泛型编程)类型无关和模板编译
  5. 【软考高项】信息系统项目管理师 论文写作技巧分享 (下)
  6. leetcode —— 16. 最接近的三数之和
  7. python 字典默认会引用 除非深拷贝
  8. VC++等待光标的两种实现方式
  9. mac apache php.ini,Mac自带的Apache使用详解
  10. [转] Java/JSP中使用JDBC连接SQL Server 2005
  11. Gentle.NET笔记(二)-列表示例
  12. 软件工程期末笔记整理
  13. ESD元器件防护原理及选型
  14. 工业物联网安全需要一揽子服务商
  15. 2023年广东数据分析师CPDA认证招生简章(理论+实战)
  16. python散点图获取边界_将曲线拟合到散点图的边界
  17. Ubuntu下安装Moodle平台
  18. 腾讯云数据库TDSQL-单机安装体验安装脚本分析
  19. VirtualBox+Vagrant报错
  20. 网络红人 赔本赚吆喝?炙手可热却苦水满腹图

热门文章

  1. 忆往昔峥嵘岁月稠——看苹果第一代iPhone的“风骚”往事
  2. XXXX is not in the sudoers file. This incident will be reported解决方法
  3. Matlab自相关/互相关函数xcorr
  4. Tomcat9的安装教程及部署自己的第一个网页
  5. idea2019 配置Tomcat9
  6. Android Audio开发——AAudio基础(十五)
  7. 期刊分区以及影响因子是什么?
  8. Python3 安装Crypto模块
  9. Antimalware Service Executable 高内存 处理办法
  10. [技术漫谈]400G时代来临,针对系统级的高速网络系统测试需要准备哪些环境