`
liaobinxu
  • 浏览: 43295 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java反射机制与动态代理

阅读更多

java反射机制与动态代理

1 java反射机制:运行时的类信息

Class类与java.lang.reflect类库一起对反射概念进行了支持,该类库包含了Field,Method以及Constructor类。这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员。这样就可以使用Constructor创建新的对象,用get()与set()方法读取与修改与Field对象相关的字段,用invoke()方法调用与Method对象相关的方法等等。

 

2 动态代理:

代理模式:为了提供额外的或不同的操作,而插入的用来代替“实际”对象。这些操作通常涉及与“实际”对象的通讯,因此代理通常充当着中间人的角色。

动态代理:所有的调用都会被重定向到单一的调用处理器上,他的工作是揭示调用的类型并确定相应的对策。

java反射机制实现动态代理的源码:

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

 

 

Java代码 
  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.   
  21. public class SimpleDynamicProxy {  
  22.     public static void consumer(Interface iface) {  
  23.         iface.doSomething();  
  24.         iface.somethingElse("bonobo");  
  25.     }  
  26.   
  27.     public static void main(String[] args) {  
  28.         RealObject real = new RealObject();  
  29.         consumer(real);  
  30.         // Insert a proxy and call again:  
  31.         Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class  
  32.                 .getClassLoader(), new Class[] { Interface.class },  
  33.                 new DynamicProxyHandler(real));  
  34.         consumer(proxy);  
  35.     }  
  36. }  

 当我们查看java.lang.reflect.Proxy源码,我们发现起核心作用的是ProxyGenerator.generateProxyClass(String paramString, Class[] paramArrayOfClass),最令人疑惑的问题是,代理对象和如何调用DynamicProxyHandler的invoke方法的,从源码里面我们很难发现如何处理的,对于ProxyGenerator写了一个测试类ProxyClassFile

Java代码 
  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.   
  48. }  

 

反编译SimpleDynamicProxy.class,代码初看起来有点复杂,仔细观察还是很有规律的,将SimpleDynamicProxy5个方法都重定向到invoke()方法,equals(),hashCode()和toString()都是父类Object方法,doSomething()和somethingElse()为接口方法。

Java代码 
  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. {  
  10.   private static Method m1;  
  11.   private static Method m0;  
  12.   private static Method m3;  
  13.   private static Method m4;  
  14.   private static Method m2;  
  15.   
  16.   public SimpleDynamicProxy(InvocationHandler paramInvocationHandler)  
  17.     throws   
  18.   {  
  19.     super(paramInvocationHandler);  
  20.   }  
  21.   
  22.   public final boolean equals(Object paramObject)  
  23.     throws   
  24.   {  
  25.     try  
  26.     {  
  27.       return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();  
  28.     }  
  29.     catch (RuntimeException localRuntimeException)  
  30.     {  
  31.       throw localRuntimeException;  
  32.     }  
  33.     catch (Throwable localThrowable)  
  34. font-size: 1em; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 38px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 10px; b
    分享到:
    评论

相关推荐

Global site tag (gtag.js) - Google Analytics