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 ...
随机推荐
- P2158/bzoj2190 [SDOI2008]仪仗队
P2158 [SDOI2008]仪仗队 欧拉函数 计算下三角的点数再*2+1 观察斜率,自行体会 #include<iostream> #include<cstdio> #in ...
- 使用openssl生成SSL证书完全参考手册
一般来说,配置HTTPS/SSL的步骤为: 1.生成足够强度的私钥.需要考虑:算法,广泛采用的一般是RSA.键长度,RSA默认为512,一般应选择2048.密码,虽然私钥不一定要加密存储,但是加密存储 ...
- http://bugs.mysql.com/bug.php?id=72123
今天某个环境发生了这个bug. http://bugs.mysql.com/bug.php?id=72123
- Docker搭建RabbitMQ集群
Docker搭建RabbitMQ集群 Docker安装 见官网 RabbitMQ镜像下载及配置 见此博文 集群搭建 首先,我们需要启动运行RabbitMQ docker run -d --hostna ...
- 简单的Django实现图片上传,并存储进MySQL数据库 案例——小白
目标:通过网页上传一张图片到Django后台,后台接收并存储进数据库 真是不容易!!这个案例的代码网上太乱,不适合我,自己摸索着写,终于成功了,记录一下,仅供自己参考,有的解释可能不对,自己明白就好, ...
- exp9《网络对抗》web安全基础实践201453331魏澍琛
201453331魏澍琛web安全基础实践 一.实验过程 1.webgoat开启 2.Injection Flaws练习 Command Injection 原网页中没有注入的地方,那就用burpsu ...
- 20145331魏澍琛《网络对抗》Exp5 MSF基础应用
20145331魏澍琛<网络对抗>Exp5 MSF基础应用 基础问题回答 1.用自己的话解释什么是exploit,payload,encode? exploit:渗透攻击的模块合集,将真正 ...
- node包管理工具--nvm(windows)
windows 安装nvw-windows 使用nvm工具: windows使用nvm-noinstall.zip安装 nvm-noinstall.zip 这个是绿色免安装版本,但是使用之前需要配置 ...
- jQuery 中 $( ) 函数的用法总结
摘要 jQuery对象: 具有jquery框架设置的所有功能的调用者, 就是该框架的对象 $又是什么?: $就是jQuery对象, jQuery对象为window的全局属性, 所以可以直接使用 如何自 ...
- 分布式系统一致性协议--2PC,3PC
分布式系统中最重要的一块,一致性协议,其中就包括了大名鼎鼎的Paxos算法. 2PC与3PC 在分布式系统中,每一个机器节点虽然能够明确知道自己在进行事务操作过程中的结果是成功或是失败,但是却无法直接 ...