查看JDK动态代理生成的类的内容

原文地址:https://blog.csdn.net/zknxx/article/details/77919332

首先我们先定义一个接口:

[java]  view plain  copy
  1. public interface PersonInter {  
  2.   
  3.     String test(String str);  
  4. }  
接着就是我们想的要生成的JDK代理类源码的代码:

[java]  view plain  copy
  1. public class JdkProxySourceClass {  
  2.   
  3.     public static void writeClassToDisk(String path){  
  4.   
  5.         byte[] classFile = ProxyGenerator.generateProxyClass("$proxy4"new Class[]{PersonInter.class});  
  6.         FileOutputStream fos = null;  
  7.         try {  
  8.             fos = new FileOutputStream(path);  
  9.             fos.write(classFile);  
  10.             fos.flush();  
  11.         } catch (FileNotFoundException e) {  
  12.             e.printStackTrace();  
  13.         } catch (IOException e) {  
  14.             e.printStackTrace();  
  15.         }finally{  
  16.             if(fos != null){  
  17.                 try {  
  18.                     fos.close();  
  19.                 } catch (IOException e) {  
  20.                     e.printStackTrace();  
  21.                 }  
  22.             }  
  23.         }  
  24.     }  
  25.   
  26.     @Test    
  27.     public void testGenerateProxyClass() {    
  28.         JdkProxySourceClass.writeClassToDisk("D:/$Proxy4.class");    
  29.     }    
  30. }  
重要的就是这一句话:byte[] classFile = ProxyGenerator.generateProxyClass("$proxy4", new Class[]{PersonInter.class});

OK接下来我们用反编译工具看一下生成的代理类源码:

[java]  view plain  copy
  1. import com.zkn.newlearn.gof.proxyhandler.PersonInter;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. import java.lang.reflect.UndeclaredThrowableException;  
  6.   
  7. public final class Proxy4 extends Proxy  
  8.   implements PersonInter  
  9. {  
  10.   private static Method m1;  
  11.   private static Method m2;  
  12.   private static Method m3;  
  13.   private static Method m0;  
  14.   
  15.   public Proxy4(InvocationHandler paramInvocationHandler)  
  16.     throws   
  17.   {  
  18.     super(paramInvocationHandler);  
  19.   }  
  20.   
  21.   public final boolean equals(Object paramObject)  
  22.     throws   
  23.   {  
  24.     try  
  25.     {  
  26.       return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();  
  27.     }  
  28.     catch (RuntimeException localRuntimeException)  
  29.     {  
  30.       throw localRuntimeException;  
  31.     }  
  32.     catch (Throwable localThrowable)  
  33.     {  
  34.       throw new UndeclaredThrowableException(localThrowable);  
  35.     }  
  36.   }  
  37.   
  38.   public final String toString()  
  39.     throws   
  40.   {  
  41.     try  
  42.     {  
  43.       return ((String)this.h.invoke(this, m2, null));  
  44.     }  
  45.     catch (RuntimeException localRuntimeException)  
  46.     {  
  47.       throw localRuntimeException;  
  48.     }  
  49.     catch (Throwable localThrowable)  
  50.     {  
  51.       throw new UndeclaredThrowableException(localThrowable);  
  52.     }  
  53.   }  
  54.   
  55.   public final String test(String paramString)  
  56.     throws   
  57.   {  
  58.     try  
  59.     {  
  60.       return ((String)this.h.invoke(this, m3, new Object[] { paramString }));  
  61.     }  
  62.     catch (RuntimeException localRuntimeException)  
  63.     {  
  64.       throw localRuntimeException;  
  65.     }  
  66.     catch (Throwable localThrowable)  
  67.     {  
  68.       throw new UndeclaredThrowableException(localThrowable);  
  69.     }  
  70.   }  
  71.   
  72.   public final int hashCode()  
  73.     throws   
  74.   {  
  75.     try  
  76.     {  
  77.       return ((Integer)this.h.invoke(this, m0, null)).intValue();  
  78.     }  
  79.     catch (RuntimeException localRuntimeException)  
  80.     {  
  81.       throw localRuntimeException;  
  82.     }  
  83.     catch (Throwable localThrowable)  
  84.     {  
  85.       throw new UndeclaredThrowableException(localThrowable);  
  86.     }  
  87.   }  
  88.   
  89.   static  
  90.   {  
  91.     try  
  92.     {  
  93.       m1 = Class.forName("java.lang.Object").getMethod("equals"new Class[] { Class.forName("java.lang.Object") });  
  94.       m2 = Class.forName("java.lang.Object").getMethod("toString"new Class[0]);  
  95.       m3 = Class.forName("com.zkn.newlearn.gof.proxyhandler.PersonInter").getMethod("test"new Class[] { Class.forName("java.lang.String") });  
  96.       m0 = Class.forName("java.lang.Object").getMethod("hashCode"new Class[0]);  
  97.       return;  
  98.     }  
  99.     catch (NoSuchMethodException localNoSuchMethodException)  
  100.     {  
  101.       throw new NoSuchMethodError(localNoSuchMethodException.getMessage());  
  102.     }  
  103.     catch (ClassNotFoundException localClassNotFoundException)  
  104.     {  
  105.       throw new NoClassDefFoundError(localClassNotFoundException.getMessage());  
  106.     }  
  107.   }  
  108. }  


从反编译出来的源码中我们可以看到在静态代码块中得到了equals、toString、hashCode和PersonInter接口中test方法的Method对象。当我们调用PersonInter中的test方法的时候:

[java]  view plain  copy
  1. public final String test(String paramString)  
  2.   throws   
  3. {  
  4.   try  
  5.   {  
  6.     return ((String)this.h.invoke(this, m3, new Object[] { paramString }));  
  7.   }  
  8.   catch (RuntimeException localRuntimeException)  
  9.   {  
  10.     throw localRuntimeException;  
  11.   }  
  12.   catch (Throwable localThrowable)  
  13.   {  
  14.     throw new UndeclaredThrowableException(localThrowable);  
  15.   }  
  16. }  

其实是调用了InvocationHandler中的invoke方法,并传入了之前获取到的对应的Method和参数。在这里也简单的说一下为什么JDK的动态代理只能代理接口不能代理类,请注意看我们所得到的代理类的源码,注意看这一句:public final class Proxy4 extends Proxy implements PersonInter。生成的代理类默认继承了Proxy这个类,而java中又是单继承的,所以这里只能代理接口,不能代理类了。就像枚举类,不能继承别的枚举类一样。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值