dubbo为consumer创建代理
ReferenceConfig.init()方法中获取到了最终的代理对象,先观察一下代理对象的视图。
默认使用javassist生成动态类,可配置proxy为jdk,则使用jdk动态代理:
<dubbo:reference id="hello" interface="com.zhang.HelloService" proxy="jdk" merger="true" check="false"/>
jdk代理对象视图如下图:
RegistryDirectory中有一个 urlInvokerMap。
// Map<url, Invoker> cache service url to invoker mapping.
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×tamp=1516256748120
值: com.alibaba.dubbo.registry.integration.RegistryDirectory$InvokerDelegete@4147e2b6
然后分析代理的创建过程,主要的调用栈如下:
贴出Protocol$Adpative的代码:
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
public void destroy() {
throw new UnsupportedOperationException(
"method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
} public int getDefaultPort() {
throw new UnsupportedOperationException(
"method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
} public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0,
com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {
if (arg1 == null)
throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg1;
//url不同,获得的扩展名是不一样的
String extName = (url.getProtocol() == null ? "dubbo" : url
.getProtocol());
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
+ url.toString() + ") use keys([protocol])");
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
.getExtension(extName);
return extension.refer(arg0, arg1);
} public com.alibaba.dubbo.rpc.Exporter export(
com.alibaba.dubbo.rpc.Invoker arg0)
throws com.alibaba.dubbo.rpc.Invoker {
if (arg0 == null)
throw new IllegalArgumentException(
"com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null)
throw new IllegalArgumentException(
"com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = (url.getProtocol() == null ? "dubbo" : url
.getProtocol());
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url("
+ url.toString() + ") use keys([protocol])");
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class)
.getExtension(extName);
return extension.export(arg0);
}
}
从调用栈可以看到,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®istry=zookeeper×tamp=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×tamp=1516461886484)
//ProtocolListenerWrapper类
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
//先进这个分支
return protocol.refer(type, url);
}
//后续再进这个分支
return new ListenerInvokerWrapper<T>(protocol.refer(type, url),
Collections.unmodifiableList(
ExtensionLoader.getExtensionLoader(InvokerListener.class)
.getActivateExtension(url, Constants.INVOKER_LISTENER_KEY)));
} //ProtocolFilterWrapper类
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
//先进这个分支
return protocol.refer(type, url);
}
//后续再进这个分支
return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER);
}
ReferenceConfig<T>的createProxy方法负责创建代理,分析之后得到的步骤大致如下:
1. 生成invoker
// ReferenceConfig.createProxy方法。refprotocol是Protocol$Adpative对象
invoker = refprotocol.refer(interfaceClass, url);
1.1 生成filter链(使用内部类把filter和next封装起来。相当于创建一个类,有Filter属性,和Invoker属性)
//ProtocolFilterWrapper类
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
// ConsumerContextFilter, MonitorFilter, FutureFilter
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (filters.size() > 0) {
for (int i = filters.size() - 1; i >= 0; i --) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
public Class<T> getInterface() {
return invoker.getInterface();
}
public URL getUrl() {
return invoker.getUrl();
}
public boolean isAvailable() {
return invoker.isAvailable();
}
public Result invoke(Invocation invocation) throws RpcException {
return filter.invoke(next, invocation);
}
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
1.2 生成RegistryDirectory$InvokerDelegete对象
// RegistryDirectory.toInvokers
// protocol.refer(serviceType, url)就是调用Protocol$Adpative的refer方法,即递归调用
invoker = new InvokerDelegete<T>(protocol.refer(serviceType, url), url, providerUrl);
1.3 生成MockClusterInvoker。涉及2个类:Protocol$Adpative和Cluster$Adpative,调用栈如下,
package com.alibaba.dubbo.rpc.cluster;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Cluster$Adpative implements com.alibaba.dubbo.rpc.cluster.Cluster {
public com.alibaba.dubbo.rpc.Invoker join(
com.alibaba.dubbo.rpc.cluster.Directory arg0)
throws com.alibaba.dubbo.rpc.cluster.Directory {
if (arg0 == null)
throw new IllegalArgumentException(
"com.alibaba.dubbo.rpc.cluster.Directory argument == null");
if (arg0.getUrl() == null)
throw new IllegalArgumentException(
"com.alibaba.dubbo.rpc.cluster.Directory argument getUrl() == null");
com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("cluster", "failover");
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.rpc.cluster.Cluster) name from url("
+ url.toString() + ") use keys([cluster])");
com.alibaba.dubbo.rpc.cluster.Cluster extension = (com.alibaba.dubbo.rpc.cluster.Cluster) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.rpc.cluster.Cluster.class)
.getExtension(extName);
// extension是MockClusterWrapper
return extension.join(arg0);
}
}
2. 创建代理。
private static final ProxyFactory proxyFactory =
ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
private T createProxy(Map<String, String> map) {
// 省略其他代码
return (T) proxyFactory.getProxy(invoker);
}
/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.ProxyFactory文件内容:
stub=com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
jdk=com.alibaba.dubbo.rpc.proxy.jdk.JdkProxyFactory
javassist=com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory
可以看到上面有一个wrapper,所以调用getExtension方法获得的扩展是StubProxyFactoryWrapper。
动态生成的ProxyFactory$Adpative类代码,格式化如下:
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class ProxyFactory$Adpative implements com.alibaba.dubbo.rpc.ProxyFactory {
public java.lang.Object getProxy(com.alibaba.dubbo.rpc.Invoker arg0)
throws com.alibaba.dubbo.rpc.Invoker {
if (arg0 == null)
throw new IllegalArgumentException(
"com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null)
throw new IllegalArgumentException(
"com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");
com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = url.getParameter("proxy", "javassist");
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
+ url.toString() + ") use keys([proxy])");
com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class)
.getExtension(extName);
// extension其实是StubProxyFactoryWrapper对象,对JavassistProxyFactory做一个wrap
return extension.getProxy(arg0);
} public com.alibaba.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0,
java.lang.Class arg1, com.alibaba.dubbo.common.URL arg2)
throws java.lang.Object {
if (arg2 == null)
throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg2;
String extName = url.getParameter("proxy", "javassist");
if (extName == null)
throw new IllegalStateException(
"Fail to get extension(com.alibaba.dubbo.rpc.ProxyFactory) name from url("
+ url.toString() + ") use keys([proxy])");
com.alibaba.dubbo.rpc.ProxyFactory extension = (com.alibaba.dubbo.rpc.ProxyFactory) ExtensionLoader
.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class)
.getExtension(extName);
return extension.getInvoker(arg0, arg1, arg2);
}
}
所以getExtension的返回对象是:StubProxyFactoryWrapper/JavassistProxyFactory
// JavassistProxyFactory
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
//一、 Proxy p = Proxy.getProxy(interfaces);
//二、 p.newInstance(new InvokerInvocationHandler(invoker));
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}
Proxy0和proxy0是javassist动态生成的类:其中p是Proxy0实例,调用newInstance(InvocationHandler)方法创建proxy0实例。
下面是推测的代码(大概):
class com.alibaba.dubbo.common.bytecode.Proxy0 extends com.alibaba.dubbo.common.bytecode.Proxy {
public Object newInstance(java.lang.reflect.InvocationHandler h){
return new com.alibaba.dubbo.common.bytecode.proxy0($1);
}
} class com.alibaba.dubbo.common.bytecode.proxy0 implements
com.alibaba.dubbo.rpc.service.EchoService, com.zhang.HelloService {
public <init>(java.lang.reflect.InvocationHandler arg0){
handler=$1;
}
public static java.lang.reflect.Method[] methods;
private java.lang.reflect.InvocationHandler handler; public java.lang.String sayHello(){
Object[] args = new Object[0];
Object ret = handler.invoke(this, methods[0], args);
return (java.lang.String)ret;
}
public java.lang.Object $echo(java.lang.Object arg0){
Object[] args = new Object[1];
args[0] = ($w)$1;
Object ret = handler.invoke(this, methods[1], args);
return (java.lang.Object)ret;
}
}
dubbo为consumer创建代理的更多相关文章
- 161130、Dubbo+SpringMVC工程创建详解
Dubbo出现的目的是为了应对现在高并发,高数据量请求的问题.目前的垂直应用架构已经无法满足现在大数据的冲击,SOA就应运而生,而Dubbo在国内使用的还是比较多,稳定性也比较不错. 架构 节点角色说 ...
- Dubbo原理实现之代理接口的定义
Dubbo有很多的实现采用了代码模式,Dubbo由代理工厂ProxyFactory对象创建代理对象. ProxyFactory接口的定义如下: @SPI("javassist") ...
- Entity Framework 6 Recipes 2nd Edition(13-10)译 -> 显式创建代理
问题 你有一个POCO实体,原本在执行一个查询时动态创建代理,现在你不想EF延迟创建代理带来的代价. 解决方案 假设你有一个如图Figure13-15的模型 Figure 13-15. A model ...
- SQL Server Alwayson创建代理作业注意事项
介绍 Always On 可用性组活动辅助功能包括支持在辅助副本上执行备份操作. 备份操作可能会给 I/O 和 CPU 带来很大的压力(使用备份压缩). 将备份负荷转移到已同步或正在同步的辅助副本后, ...
- Spring AOP 自动创建代理
Spring为我们提供了自动代理机制,让容器为我们自动生成代理,把我们从烦琐的配置工作中解放出来,在内部,Spring 使用BeanPostProcessor自动地完成这项工作. 1.实现 ...
- Spring AOP 源码分析 - 创建代理对象
1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...
- 关于spring.net的面向切面编程 (Aspect Oriented Programming with Spring.NET)-使用工厂创建代理(Using the ProxyFactoryObject to create AOP proxies)
本文翻译自Spring.NET官方文档Version 1.3.2. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他人提供帮助. 侵删. 如果你正在为你的业务模型使用 ...
- Spring Aop(十四)——Aop自动创建代理对象的原理
转发地址:https://www.iteye.com/blog/elim-2398725 Aop自动创建代理对象的原理 我们在使用Spring Aop时,通常Spring会自动为我们创建目标bean的 ...
- Spring Aop(十三)——ProxyFactoryBean创建代理对象
转发地址:https://www.iteye.com/blog/elim-2398673 ProxyFactoryBean创建代理对象 ProxyFactoryBean实现了Spring的Factor ...
随机推荐
- 关于windows下c++生成的exe发布时的依赖dll问题
如同linux下通常要求安装特定版本的libstdc++一样,windows下vc++生成的exe发布时的依赖dll问题,可以参见帖子,http://bbs.csdn.net/topics/39105 ...
- Socket:读写处理及连接断开的检测
作为进程间通信及网络通信的一种重要技术,在实际的开发中,socket编程是经常被用到的.关于socket编程的一般步骤,这里不再赘述,相关资料和文章很多,google/baidu即可. 本文主要是探讨 ...
- 认识epoll
linux下的epoll(7)函数,其有着良好的就绪事件通知机制.Epoll 是被linux2.6开始引进的,但是不被其他的类UNIX系统支持,它提供了一种类似select或poll函数的机制:a. ...
- Python3基础 str find+index 是否存在指定字符串,有则返回第一个索引值
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- git如何列出最简短的commit(tag和head名都不显示)
答:git log --oneline --no-decorate --oneline: 将commit显示成一行 --no-decorate: 将tag和head名隐藏掉
- 51nod 1242 斐波那契数列的第N项
之前一直没敢做矩阵一类的题目 其实还好吧 推荐看一下 : http://www.cnblogs.com/SYCstudio/p/7211050.html 但是后面的斐波那契 推导不是很懂 前面讲的挺 ...
- [IDEA插件] - 一个不错的插件
今天看到微信平台一篇推送IDEA插件的文章继而下载了个插件看了下. 名字叫做codehelper.generator codehelper.generator http://plugins.jetbr ...
- The way to Go(3): 安装Go环境
Reference: Github: Go Github: The way to Go 在mac上安装Go语言初体验 安装Go环境 Go 语言开发团队开发了适用于以下操作系统的编译器: Linux F ...
- 关于C++中的友元函数的总结
1.友元函数的简单介绍 1.1为什么要使用友元函数 在实现类之间数据共享时,减少系统开销,提高效率.如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数.具 ...
- win10 操作系统 修改桌面图标
桌面右击出现菜单后,点击个性化: 点击左边菜单的主题,点击桌面图标设置,在新窗口中选择需要显示的图标接口 details please check following screenshot