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方法的了。

你可能感兴趣的:(java,动态代理)