Dubbo源码分析之JavassistProxy代理---(十四)

本源码主要是基于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

相关文章
相关标签/搜索