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. mysql 匹配 findinset
  2. struts2 学习记录 之 国际化
  3. vi/vim命令怎么在Linux系统中使用
  4. 前缀、中缀和后缀表达式详解,中缀表达式到后缀表达式的转换规则,以及后缀表达式的计算规则,附计算代码
  5. 小学C++编程入门书籍及相关资料介绍(二) 算法篇
  6. 网页文字无法复制解决方法
  7. 学习Python可以从事哪些工作?
  8. div垂直,水平居中
  9. JAVA 【引用类型】和【对象类型】在【继承】中的异同
  10. 独立站现在好不好做?
  11. 正负电子碰撞湮灭,电荷哪里去了
  12. 将中文版pycharm改成英文版
  13. 乐高spike python_SPIKE Prime科创套装 篇四:乐高教育SPIKE Prime入门编程和搭建活动教学...
  14. 四城市十行业紧缺人才信息公布
  15. tools: USB、MiniUSB、MicroUSB接线
  16. Codeforces Gym 100015H Hidden Code(暴力)
  17. solidwork 侵权 证据_企业常见版权侵权问题咨询总结
  18. Cocos2dx游戏开发系列笔记5:继续润色《忍者飞镖射幽灵》(VS2013快捷键)
  19. ValueError: Classification metrics can‘t handle a mix of binary and continuous targets
  20. 华云数据出席2021信创发展论坛:喜获信创双项殊荣 发布业内首个《信创云基座白皮书》

热门文章

  1. 用Java实现一个区块链系统 附源码!
  2. 最新苍穹广告精灵区块链源码更新版
  3. vue之el-form实现常用表单验证规则定义【比如:用户名、密码、身份证号、邮箱号,手机号,车牌号、ip地址等】|亲测有效,建议收藏
  4. [中英文对照]常见大学课程名称翻译
  5. Airbnb系列三《Managing Diversity in Airbnb Search》 搜索多样性
  6. 蔡高厅高等数学22-导数的概念、两种表现形式
  7. Java-String长度限制
  8. 【综合实验】之 SNAT 和 DNAT
  9. 计算机实践的重要性2
  10. Window 环境下构建React APP