java反射機制與動態代理

 1 java反射機制:運行時的類信息

Class類與java.lang.reflect類庫一起對反射概念進行了支持,該類庫包含了Field,Method以及Constructor類。這些類型的對象是由JVM在運行時創建的,用以表示未知類裏對應的成員。這樣就可以使用Constructor創建新的對象,用get()與set()方法讀取與修改與Field對象相關的字段,用invoke()方法調用與Method對象相關的方法等等。

 

2 動態代理:

代理模式:爲了提供額外的或不同的操作,而插入的用來代替“實際”對象。這些操作通常涉及與“實際”對象的通訊,因此代理通常充當着中間人的角色。

動態代理:所有的調用都會被重定向到單一的調用處理器上,他的工作是揭示調用的類型並確定相應的對策。

java反射機制實現動態代理的源碼:

 

  1. interface Interface { 
  2.   void doSomething(); 
  3.   void somethingElse(String arg); 
  4.  
  5. class RealObject implements Interface { 
  6.   public void doSomething() { print("doSomething"); } 
  7.   public void somethingElse(String arg) { 
  8.     print("somethingElse " + arg); 
  9.   } 

  1. import java.lang.reflect.*; 
  2.  
  3. class DynamicProxyHandler implements InvocationHandler { 
  4.     private Object proxied; 
  5.  
  6.     public DynamicProxyHandler(Object proxied) { 
  7.         this.proxied = proxied; 
  8.     } 
  9.  
  10.     public Object invoke(Object proxy, Method method, Object[] args) 
  11.             throws Throwable { 
  12.         System.out.println("**** proxy: " + proxy.getClass() + ", method: " 
  13.                 + method + ", args: " + args); 
  14.         if (args != null
  15.             for (Object arg : args) 
  16.                 System.out.println("  " + arg); 
  17.         return method.invoke(proxied, args); 
  18.     } 
  19.  
  20. public class SimpleDynamicProxy { 
  21.     public static void consumer(Interface iface) { 
  22.         iface.doSomething(); 
  23.         iface.somethingElse("bonobo"); 
  24.     } 
  25.  
  26.     public static void main(String[] args) { 
  27.         RealObject real = new RealObject(); 
  28.         consumer(real); 
  29.         // Insert a proxy and call again: 
  30.         Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class 
  31.                 .getClassLoader(), new Class[] { Interface.class }, 
  32.                 new DynamicProxyHandler(real)); 
  33.         consumer(proxy); 
  34.     } 

當我們查看java.lang.reflect.Proxy源碼,我們發現起核心作用的是ProxyGenerator.generateProxyClass(String paramString, Class[] paramArrayOfClass),最令人疑惑的問題是,代理對象和如何調用DynamicProxyHandler的invoke方法的,從源碼裏面我們很難發現如何處理的,對於ProxyGenerator寫了一個測試類ProxyClassFile

 

  1. import java.io.File; 
  2. import java.io.FileNotFoundException; 
  3. import java.io.FileOutputStream; 
  4. import java.io.IOException; 
  5.  
  6. import sun.misc.ProxyGenerator; 
  7.  
  8. public class ProxyClassFile { 
  9.  
  10.     public static void main(String[] args) { 
  11.  
  12.         String proxyName = "SimpleDynamicProxy"
  13.  
  14.         RealObject t = new RealObject(); 
  15.  
  16.         Class[] interfaces = t.getClass().getInterfaces(); 
  17.  
  18.         byte[] proxyClassFile = ProxyGenerator.generateProxyClass( 
  19.  
  20.         proxyName, interfaces); 
  21.  
  22.         File f = new File("E:/workspace/TIJ4/bin/typeinfo/SimpleDynamicProxy.class"); 
  23.  
  24.         try { 
  25.  
  26.             FileOutputStream fos = new FileOutputStream(f); 
  27.  
  28.             fos.write(proxyClassFile); 
  29.  
  30.             fos.flush(); 
  31.  
  32.             fos.close(); 
  33.  
  34.         } catch (FileNotFoundException e) { 
  35.  
  36.             e.printStackTrace(); // To change body of catch statement use File | 
  37.                                     // Settings | File Templates. 
  38.  
  39.         } catch (IOException e) { 
  40.  
  41.             e.printStackTrace(); // To change body of catch statement use File | 
  42.                                     // Settings | File Templates. 
  43.  
  44.         } 
  45.  
  46.     } 
  47.  

反編譯SimpleDynamicProxy.class,代碼初看起來有點複雜,仔細觀察還是很有規律的,將SimpleDynamicProxy5個方法都重定向到invoke()方法,equals(),hashCode()和toString()都是父類Object方法,doSomething()和somethingElse()爲接口方法。

 

  1. import java.lang.reflect.InvocationHandler; 
  2. import java.lang.reflect.Method; 
  3. import java.lang.reflect.Proxy; 
  4. import java.lang.reflect.UndeclaredThrowableException; 
  5. import typeinfo.Interface; 
  6.  
  7. public final class SimpleDynamicProxy extends Proxy 
  8.   implements Interface 
  9.   private static Method m1; 
  10.   private static Method m0; 
  11.   private static Method m3; 
  12.   private static Method m4; 
  13.   private static Method m2; 
  14.  
  15.   public SimpleDynamicProxy(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 int hashCode() 
  39.     throws  
  40.   { 
  41.     try 
  42.     { 
  43.       return ((Integer)this.h.invoke(this, m0, null)).intValue(); 
  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 void doSomething() 
  56.     throws  
  57.   { 
  58.     try 
  59.     { 
  60.       this.h.invoke(this, m3, null); 
  61.       return
  62.     } 
  63.     catch (RuntimeException localRuntimeException) 
  64.     { 
  65.       throw localRuntimeException; 
  66.     } 
  67.     catch (Throwable localThrowable) 
  68.     { 
  69.       throw new UndeclaredThrowableException(localThrowable); 
  70.     } 
  71.   } 
  72.  
  73.   public final void somethingElse(String paramString) 
  74.     throws  
  75.   { 
  76.     try 
  77.     { 
  78.       this.h.invoke(this, m4, new Object[] { paramString }); 
  79.       return
  80.     } 
  81.     catch (RuntimeException localRuntimeException) 
  82.     { 
  83.       throw localRuntimeException; 
  84.     } 
  85.     catch (Throwable localThrowable) 
  86.     { 
  87.       throw new UndeclaredThrowableException(localThrowable); 
  88.     } 
  89.   } 
  90.  
  91.   public final String toString() 
  92.     throws  
  93.   { 
  94.     try 
  95.     { 
  96.       return (String)this.h.invoke(this, m2, null); 
  97.     } 
  98.     catch (RuntimeException localRuntimeException) 
  99.     { 
  100.       throw localRuntimeException; 
  101.     } 
  102.     catch (Throwable localThrowable) 
  103.     { 
  104.       throw new UndeclaredThrowableException(localThrowable); 
  105.     } 
  106.   } 
  107.  
  108.   static 
  109.   { 
  110.     try 
  111.     { 
  112.       m1 = Class.forName("java.lang.Object").getMethod("equals"new Class[] { Class.forName("java.lang.Object") }); 
  113.       m0 = Class.forName("java.lang.Object").getMethod("hashCode"new Class[0]); 
  114.       m3 = Class.forName("typeinfo.Interface").getMethod("doSomething"new Class[0]); 
  115.       m4 = Class.forName("typeinfo.Interface").getMethod("somethingElse"new Class[] { Class.forName("java.lang.String") }); 
  116.       m2 = Class.forName("java.lang.Object").getMethod("toString"new Class[0]); 
  117.       return
  118.     } 
  119.     catch (NoSuchMethodException localNoSuchMethodException) 
  120.     { 
  121.       throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); 
  122.     } 
  123.     catch (ClassNotFoundException localClassNotFoundException) 
  124.     { 
  125.       throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); 
  126.     } 
  127.   } 

通過源代碼我們不難看出,代理類是如何調用invoke方法的了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章