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

相關文章
相關標籤/搜索