ReferenceConfig.init()方法中获取到了最终的代理对象,先观察一下代理对象的视图。

默认使用javassist生成动态类,可配置proxy为jdk,则使用jdk动态代理:

  1. <dubbo:reference id="hello" interface="com.zhang.HelloService" proxy="jdk" merger="true" check="false"/>

jdk代理对象视图如下图:

RegistryDirectory中有一个 urlInvokerMap。

  1. // Map<url, Invoker> cache service url to invoker mapping.
  2. private volatile Map<String, Invoker<T>> urlInvokerMap;

示例:

键: dubbo://192.168.233.6:20880/com.zhang.HelloService?anyhost=true&application=consumerk_app&check=false&dubbo=2.5.2&group=a&interface=com.zhang.HelloService&iothreads=2&merger=true&methods=sayHello,sayException,sayHi,sayFuck&pid=6736&sayException.retries=0&sayFuck.retries=0&sayFuck.return=true&sayHello.retries=0&sayHi.retries=0&side=consumer&timeout=6000&timestamp=1516256748120
值: com.alibaba.dubbo.registry.integration.RegistryDirectory$InvokerDelegete@4147e2b6

然后分析代理的创建过程,主要的调用栈如下:

贴出Protocol$Adpative的代码:

  1. package com.alibaba.dubbo.rpc;
  2. import com.alibaba.dubbo.common.extension.ExtensionLoader;
  3. public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
  4. public void destroy() {
  5. throw new UnsupportedOperationException(
  6. "method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
  7. }
  8.  
  9. public int getDefaultPort() {
  10. throw new UnsupportedOperationException(
  11. "method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
  12. }
  13.  
  14. public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0,
  15. com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {
  16. if (arg1 == null)
  17. throw new IllegalArgumentException("url == null");
  18. com.alibaba.dubbo.common.URL url = arg1;
  19. //url不同,获得的扩展名是不一样的
  20. String extName = (url.getProtocol() == null ? "dubbo" : url
  21. .getProtocol());
  22. if (extName == null)
  23. throw new IllegalStateException(
  24. "Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
  25. + url.toString() + ") use keys([protocol])");
  26. com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
  27. .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
  28. .getExtension(extName);
  29. return extension.refer(arg0, arg1);
  30. }
  31.  
  32. public com.alibaba.dubbo.rpc.Exporter export(
  33. com.alibaba.dubbo.rpc.Invoker arg0)
  34. throws com.alibaba.dubbo.rpc.Invoker {
  35. if (arg0 == null)
  36. throw new IllegalArgumentException(
  37. "com.alibaba.dubbo.rpc.Invoker argument == null");
  38. if (arg0.getUrl() == null)
  39. throw new IllegalArgumentException(
  40. "com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
  41. com.alibaba.dubbo.common.URL url = arg0.getUrl();
  42. String extName = (url.getProtocol() == null ? "dubbo" : url
  43. .getProtocol());
  44. if (extName == null)
  45. throw new IllegalStateException(
  46. "Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
  47. + url.toString() + ") use keys([protocol])");
  48. com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
  49. .getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
  50. .getExtension(extName);
  51. return extension.export(arg0);
  52. }
  53. }

从调用栈可以看到,Protocol\$Adpative.refer(Class, URL)调用了2次。但是传递的URL参数是不一样的,

第一次获取的protocol是 ProtocolFilterWrapper/ProtocolListenerWrapper/RegistryProtocol,
第二次获取的protocol是 ProtocolFilterWrapper/ProtocolListenerWrapper/DubboProtocol。

所以在ProtocolListenerWrapper和ProtocolFilterWrapper中走的分支不同。
(第一次的URL是:
registry://192.168.153.1:2181/com.alibaba.dubbo.registry.RegistryService?application=consumer&dubbo=2.1.2&localhost=true&pid=2504&refer=application%3Dconsumer%26dubbo%3D2.1.2%26interface%3Dcom.zhang.HelloService%26methods%3DsayHello%26pid%3D2504%26timestamp%3D1516461886484&registry=zookeeper&timestamp=1516461886531
Protocol$Adpative.refer的refer方法中,getExtension()返回的扩展是ProtocolListenerWrapper/ProtocolFilterWrapper/RegistryProtocol。
第二次的URL是:
dubbo://192.168.153.1:20880/com.zhang.HelloService?anyhost=true&application=consumer&check=false&dubbo=2.1.2&interface=com.zhang.HelloService&methods=sayHello&pid=2504&timestamp=1516461886484)

  1. //ProtocolListenerWrapper类
  2. public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
  3. if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
  4. //先进这个分支
  5. return protocol.refer(type, url);
  6. }
  7. //后续再进这个分支
  8. return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
  9. Collections.unmodifiableList(
  10. ExtensionLoader.getExtensionLoader(InvokerListener.class)
  11. .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
  12. }
  13.  
  14. //ProtocolFilterWrapper类
  15. public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
  16. if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
  17. //先进这个分支
  18. return protocol.refer(type, url);
  19. }
  20. //后续再进这个分支
  21. return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
  22. }

ReferenceConfig<T>的createProxy方法负责创建代理,分析之后得到的步骤大致如下:

1. 生成invoker

  1. // ReferenceConfig.createProxy方法。refprotocol是Protocol$Adpative对象
  2. invoker = refprotocol.refer(interfaceClass, url);

1.1 生成filter链(使用内部类把filter和next封装起来。相当于创建一个类,有Filter属性,和Invoker属性)

  1. //ProtocolFilterWrapper类
  2. private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
  3. Invoker<T> last = invoker;
    // ConsumerContextFilter, MonitorFilter, FutureFilter
  4. List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
  5. if (filters.size() > 0) {
  6. for (int i = filters.size() - 1; i >= 0; i --) {
  7. final Filter filter = filters.get(i);
  8. final Invoker<T> next = last;
  9. last = new Invoker<T>() {
  10. public Class<T> getInterface() {
  11. return invoker.getInterface();
  12. }
  13. public URL getUrl() {
  14. return invoker.getUrl();
  15. }
  16. public boolean isAvailable() {
  17. return invoker.isAvailable();
  18. }
  19. public Result invoke(Invocation invocation) throws RpcException {
  20. return filter.invoke(next, invocation);
  21. }
  22. public void destroy() {
  23. invoker.destroy();
  24. }
  25. @Override
  26. public String toString() {
  27. return invoker.toString();
  28. }
  29. };
  30. }
  31. }
  32. return last;
  33. }

1.2 生成RegistryDirectory$InvokerDelegete对象

  1. // RegistryDirectory.toInvokers
    // protocol.refer(serviceType, url)就是调用Protocol$Adpative的refer方法,即递归调用
  2. invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);

1.3 生成MockClusterInvoker。涉及2个类:Protocol$Adpative和Cluster$Adpative,调用栈如下,

  1. package com.alibaba.dubbo.rpc.cluster;
  2. import com.alibaba.dubbo.common.extension.ExtensionLoader;
  3. public class Cluster$Adpative implements com.alibaba.dubbo.rpc.cluster.Cluster {
  4. public com.alibaba.dubbo.rpc.Invoker join(
  5. com.alibaba.dubbo.rpc.cluster.Directory arg0)
  6. throws com.alibaba.dubbo.rpc.cluster.Directory {
  7. if (arg0 == null)
  8. throw new IllegalArgumentException(
  9. "com.alibaba.dubbo.rpc.cluster.Directory argument == null");
  10. if (arg0.getUrl() == null)
  11. throw new IllegalArgumentException(
  12. "com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
  13. com.alibaba.dubbo.common.URL url = arg0.getUrl();
  14. String extName = url.getParameter("cluster", "failover");
  15. if (extName == null)
  16. throw new IllegalStateException(
  17. "Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url("
  18. + url.toString() + ") use keys([cluster])");
  19. com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster) ExtensionLoader
  20. .getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class)
  21. .getExtension(extName);
  22. // extension是MockClusterWrapper
  23. return extension.join(arg0);
  24. }
  25. }

2. 创建代理。

  1. private static final ProxyFactory proxyFactory =
  2. ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
  3. private T createProxy(Map<String, String> map) {
  4. // 省略其他代码
  5. return (T) proxyFactory.getProxy(invoker);
  6. }

/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.ProxyFactory文件内容:

  1. stub=com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
  2. jdk=com.alibaba.dubbo.rpc.proxy.jdk.JdkProxyFactory
  3. javassist=com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory

可以看到上面有一个wrapper,所以调用getExtension方法获得的扩展是StubProxyFactoryWrapper。

动态生成的ProxyFactory$Adpative类代码,格式化如下:

  1. package com.alibaba.dubbo.rpc;
  2. import com.alibaba.dubbo.common.extension.ExtensionLoader;
  3. public class ProxyFactory$Adpative implements com.alibaba.dubbo.rpc.ProxyFactory {
  4. public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0)
  5. throws com.alibaba.dubbo.rpc.Invoker {
  6. if (arg0 == null)
  7. throw new IllegalArgumentException(
  8. "com.alibaba.dubbo.rpc.Invoker argument == null");
  9. if (arg0.getUrl() == null)
  10. throw new IllegalArgumentException(
  11. "com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
  12. com.alibaba.dubbo.common.URL url = arg0.getUrl();
  13. String extName = url.getParameter("proxy", "javassist");
  14. if (extName == null)
  15. throw new IllegalStateException(
  16. "Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
  17. + url.toString() + ") use keys([proxy])");
  18. com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
  19. .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class)
  20. .getExtension(extName);
  21. // extension其实是StubProxyFactoryWrapper对象,对JavassistProxyFactory做一个wrap
  22. return extension.getProxy(arg0);
  23. }
  24.  
  25. public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0,
  26. java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2)
  27. throws java.lang.Object {
  28. if (arg2 == null)
  29. throw new IllegalArgumentException("url == null");
  30. com.alibaba.dubbo.common.URL url = arg2;
  31. String extName = url.getParameter("proxy", "javassist");
  32. if (extName == null)
  33. throw new IllegalStateException(
  34. "Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
  35. + url.toString() + ") use keys([proxy])");
  36. com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
  37. .getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class)
  38. .getExtension(extName);
  39. return extension.getInvoker(arg0, arg1, arg2);
  40. }
  41. }

所以getExtension的返回对象是:StubProxyFactoryWrapper/JavassistProxyFactory

  1. // JavassistProxyFactory
  2. public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
    //一、 Proxy p = Proxy.getProxy(interfaces);
  3. //二、 p.newInstance(new InvokerInvocationHandler(invoker));
  4. return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
  5. }

Proxy0和proxy0是javassist动态生成的类:其中p是Proxy0实例,调用newInstance(InvocationHandler)方法创建proxy0实例。

下面是推测的代码(大概):

  1. class com.alibaba.dubbo.common.bytecode.Proxy0 extends com.alibaba.dubbo.common.bytecode.Proxy {
  2. public Object newInstance(java.lang.reflect.InvocationHandler h){
  3. return new com.alibaba.dubbo.common.bytecode.proxy0($1);
  4. }
  5. }
  6.  
  7. class com.alibaba.dubbo.common.bytecode.proxy0 implements
  8. com.alibaba.dubbo.rpc.service.EchoService, com.zhang.HelloService {
  9. public <init>(java.lang.reflect.InvocationHandler arg0){
  10. handler=$1;
  11. }
  12. public static java.lang.reflect.Method[] methods;
  13. private java.lang.reflect.InvocationHandler handler;
  14.  
  15. public java.lang.String sayHello(){
  16. Object[] args = new Object[0];
  17. Object ret = handler.invoke(this, methods[0], args);
  18. return (java.lang.String)ret;
  19. }
  20. public java.lang.Object $echo(java.lang.Object arg0){
  21. Object[] args = new Object[1];
  22. args[0] = ($w)$1;
  23. Object ret = handler.invoke(this, methods[1], args);
  24. return (java.lang.Object)ret;
  25. }
  26. }

dubbo为consumer创建代理的更多相关文章

  1. 161130、Dubbo+SpringMVC工程创建详解

    Dubbo出现的目的是为了应对现在高并发,高数据量请求的问题.目前的垂直应用架构已经无法满足现在大数据的冲击,SOA就应运而生,而Dubbo在国内使用的还是比较多,稳定性也比较不错. 架构 节点角色说 ...

  2. Dubbo原理实现之代理接口的定义

    Dubbo有很多的实现采用了代码模式,Dubbo由代理工厂ProxyFactory对象创建代理对象. ProxyFactory接口的定义如下: @SPI("javassist") ...

  3. Entity Framework 6 Recipes 2nd Edition(13-10)译 -> 显式创建代理

    问题 你有一个POCO实体,原本在执行一个查询时动态创建代理,现在你不想EF延迟创建代理带来的代价. 解决方案 假设你有一个如图Figure13-15的模型 Figure 13-15. A model ...

  4. SQL Server Alwayson创建代理作业注意事项

    介绍 Always On 可用性组活动辅助功能包括支持在辅助副本上执行备份操作. 备份操作可能会给 I/O 和 CPU 带来很大的压力(使用备份压缩). 将备份负荷转移到已同步或正在同步的辅助副本后, ...

  5. Spring AOP 自动创建代理

        Spring为我们提供了自动代理机制,让容器为我们自动生成代理,把我们从烦琐的配置工作中解放出来,在内部,Spring 使用BeanPostProcessor自动地完成这项工作.   1.实现 ...

  6. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  7. 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)

    本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 如果你正在为你的业务模型使用 ...

  8. Spring Aop(十四)——Aop自动创建代理对象的原理

    转发地址:https://www.iteye.com/blog/elim-2398725 Aop自动创建代理对象的原理 我们在使用Spring Aop时,通常Spring会自动为我们创建目标bean的 ...

  9. Spring Aop(十三)——ProxyFactoryBean创建代理对象

    转发地址:https://www.iteye.com/blog/elim-2398673 ProxyFactoryBean创建代理对象 ProxyFactoryBean实现了Spring的Factor ...

随机推荐

  1. RabbitMQ-C 客户端接口使用说明

    rabbitmq-c是一个用于C语言的,与AMQP server进行交互的client库.AMQP协议为版本0-9-1.rabbitmq-c与server进行交互前需要首先进行login操作,在操作后 ...

  2. http://bugs.mysql.com/bug.php?id=72123

    今天某个环境发生了这个bug. http://bugs.mysql.com/bug.php?id=72123

  3. html判断当前页面是否在iframe中/顶级document中

    在使用div+iframe布局的应用中,通常我们希望在session超时或者未登录访问时跳转到登录页面,默认情况下iframe中的页面无法直接覆盖父页面,因此需要在登录页面加载的时候判断一下当前是否为 ...

  4. HTML5 表单元素和属性

    HTML5 表单元素和属性学习 版权声明:未经博主授权,内容严禁转载 ! 表单元素简介 无论实现提交功能还是展示页面功能,表单在HTML中的作用都十分重要. 在其他版本的HTML中,表单能够包含的元素 ...

  5. 微信小程序——1、文件的认识

    主体文件的构成 微信小程序的主体由三个部分组成,需放在主目录中,名称也是固定的 app.js:微信小程序的主逻辑文件,主要用来注册小程序 app.json:微信小程序的主配置文件,对微信小程序进行全局 ...

  6. SQLSERVER中order by ,group by ,having where 的先后顺序

    SELECT [Name]  FROM [LinqToSql].[dbo].[Student]  where name='***' group  by  name    having (name='* ...

  7. Linux设备驱动中的IO模型---阻塞和非阻塞IO【转】

    在前面学习网络编程时,曾经学过I/O模型 Linux 系统应用编程——网络编程(I/O模型),下面学习一下I/O模型在设备驱动中的应用. 回顾一下在Unix/Linux下共有五种I/O模型,分别是: ...

  8. [不屈的复习] - http://how2j.cn/

    http://how2j.cn/ 该教程网站分得比较规整!

  9. div滚动条时div内容显示一半

    本文为博主原创,未经允许不得转载 今天在做页面浏览器适配时,将页面中的一个div进行放大时,出现了滚动条,但滚动条对应div中的 内容只能显示一半. 仔细对应属性样式时,div具有overflow:h ...

  10. CSU 1808 地铁(最短路变形)

    http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1808 题意: Bobo 居住在大城市 ICPCCamp. ICPCCamp 有 n 个地铁站, ...