本源码主要是基于2.7.7-release版本. Dubbo中代理的扩展点是ProxyFactory接口,默认SPI扩展点是 javassist, 是经过Proxy#getProxy方案,传入接口,而后调用newInstance 建立动态代理,这里Proxy是Dubbo实现的代理抽象类,并非jdk的原生的Proxy,可是这列InvokerInvocationHandler仍是实现JDK原生的InvocationHandler接口.
经过ClassUtil#getClassLoader获取classloader,调用虫重载方法,传入classloader和代理的接口.
加下来是具体建立代理的逻辑,1 首先校验接口的数量不能超过 65535,而后把全部接口名称拼接做为缓存的key.
这是Proxy的缓存的数据结构, 就是Map嵌套的WeakHashMap 数据结构.
这里对cache操做加了一把同步锁,首先是会根据classloader取获取HashMap的缓存,而后根据key 获取代理代理,若是缓存已存在, 则直接返回缓存,没有则判断value是不是PENDING_GENERATION_MARKER(便是Object阻塞标志),若是是 则一直调用wait进行等待待代理类的建立完成,
而后建立代理类计数器加1,而后实例化ClassGenerator类, 这是Dubbo首先的字节码操做,而后检查非public接口是否来自 不一样的包,
而后遍历解析接口的方法,加入到CodeGenerator实例,
然欧建立默认生成ProxyInstance类名规则是 包名 + ".proxy" + 自增id, 生成Proxy的实例,是Proxy.class.getName() + id, 而后调用ClassGenerator生成的toClass底层是经过 javasist生成字节码,而后经过classloader记载到内存
java
Dubbo框架中没有提供将生成的字节码输出到文件的配置,因此我加了如下代码在生成字节码后,写入到文件:缓存
String proxyName = "$Proxy" + id +".class";
Path path = Paths.get(proxy
Files.write(path, mCtc.toBytecode(), new OpenOption[0]);
复制代码
而后,下面是生成的字节码反编译的文件.markdown
第一个是代理的实例的类.数据结构
public class Proxy0 extends Proxy implements DC {
public Object newInstance(InvocationHandler var1) {
return new proxy0(var1);
}
public Proxy0() {
}
}
复制代码
第二个是代理类框架
public class proxy0 implements DC, Destroyable, EchoService, DemoService {
public static Method[] methods;
private InvocationHandler handler;
public Object invoke(String var1, String var2) throws Exception {
Object[] var3 = new Object[]{var1, var2};
Object var4 = this.handler.invoke(this, methods[0], var3);
return (Object)var4;
}
public String get(CustomArgument var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[1], var2);
return (String)var3;
}
public long timestamp() {
Object[] var1 = new Object[0];
Object var2 = this.handler.invoke(this, methods[2], var1);
return var2 == null ? (long)0 : (Long)var2;
}
public int getSize(Object[] var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[3], var2);
return var3 == null ? 0 : (Integer)var3;
}
public int getSize(String[] var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[4], var2);
return var3 == null ? 0 : (Integer)var3;
}
public void $invoke(String var1, String var2) {
Object[] var3 = new Object[]{var1, var2};
this.handler.invoke(this, methods[5], var3);
}
public byte getbyte(byte var1) {
Object[] var2 = new Object[]{new Byte(var1)};
Object var3 = this.handler.invoke(this, methods[6], var2);
return var3 == null ? (byte)0 : (Byte)var3;
}
public void sayHello(String var1) {
Object[] var2 = new Object[]{var1};
this.handler.invoke(this, methods[7], var2);
}
public String getThreadName() {
Object[] var1 = new Object[0];
Object var2 = this.handler.invoke(this, methods[8], var1);
return (String)var2;
}
public int stringLength(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[9], var2);
return var3 == null ? 0 : (Integer)var3;
}
public Type enumlength(Type[] var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[10], var2);
return (Type)var3;
}
public Person getPerson(Person var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[11], var2);
return (Person)var3;
}
public String testReturnType(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[12], var2);
return (String)var3;
}
public List testReturnType1(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[13], var2);
return (List)var3;
}
public CompletableFuture testReturnType2(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[14], var2);
return (CompletableFuture)var3;
}
public CompletableFuture testReturnType3(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[15], var2);
return (CompletableFuture)var3;
}
public CompletableFuture testReturnType4(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[16], var2);
return (CompletableFuture)var3;
}
public CompletableFuture testReturnType5(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[17], var2);
return (CompletableFuture)var3;
}
public String echo(String var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[18], var2);
return (String)var3;
}
public Object $echo(Object var1) {
Object[] var2 = new Object[]{var1};
Object var3 = this.handler.invoke(this, methods[19], var2);
return (Object)var3;
}
public void $destroy() {
Object[] var1 = new Object[0];
this.handler.invoke(this, methods[20], var1);
}
public proxy0() {
}
public proxy0(InvocationHandler var1) {
this.handler = var1;
}
}
复制代码
总结: 今天主要分析了Dubbo中基于Javasist的动态代理的实现过程,针对Javasist具体详细操做须要读者对于java的字节码足够了解, 我以前分析过Java字节码文件的分析的文章,仅供参考.this