Proxy 动态代理再次理解

原创 2012年03月27日 14:19:06
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import static java.lang.System.out;
interface User{
	public abstract void say(String str);
}
class UUU implements User{
	@Override
	public void say(String str) {
		out.print(str);
	}
}
public class ProxyTest {
	public   Object target = null;
	public static void main(String args[])throws Exception {
		//System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); // 通过此语句得到动态生成 的class 文件,然后通过 反编译工具得到代码 
		User prox = (User)(new ProxyTest().bind(new UUU()));// 动态得到 proxy类,这个类继承proxy,且实现User 接口
		
	}
	public static void  proxyConstruct()throws Exception
	{
		Class<?> clazz =  Proxy.getProxyClass(Comparable.class.getClassLoader(),Comparable.class);
		Constructor cons = clazz.getConstructor(InvocationHandler.class);
		Object proxy = cons.newInstance(new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				
				return null;
			}
		});
		out.println(proxy.toString());
	}
	public static void proxyInstance()throws Exception {
		Object proxy = Proxy.newProxyInstance(Comparable.class.getClassLoader(),new Class<?>[] {Comparable.class},new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
		});
		out.println(proxy==null);
	}
	public Object bind(final Object target)
	{
		this.target = target ;
		return Proxy.newProxyInstance(Comparable.class.getClassLoader(),new Class<?>[] {Comparable.class},new InvocationHandler() {
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				out.println("begin:");
				return method.invoke(target, args); // 对于代理所执行的任何方法都将转移到这个地址执行,这也是就为什么可以添加功能的原因 
			}
		});
	}
}

/*
 * 			Proxy 原理 
 * 	 Proxy 就是动态生成一个,其实 这和代理并没有什么关系,它只是可以动态地去生成一个类,在生成
 * 	 这个类的时候,我们可以规定它的加载器,实现的接口,而Proxy 生成的这个类并代理目标类做什么,所以里面还有一个重要的成员 InvocationHandler h
 * 
 *  下面我们来分析一下  目标类(target)、代理类(proxy)、InvocationHandler(Handler)类 它们之间的关系 		
 * 		
 * 		当我们调用代理类中实现接口的方法时,如proxy.add(),会将方法名传给 代理类的 InvocationHandler 成员,而这个成员有一个 invoke 方法,所以我们
 * 		调用 proxy.add 则成了 h.invoke(this,method,args);而调用h.invoke方法,又不得不调用我们实现的invocationHandler接口里面的 invoke 方法,
 * 		而我们则在 handler.invoke 方法中调用 根据传过来的方法Method调用  Method.invoke(target,args),即,这样就成功调用了目标类里的方法
 * 		
 * 		因为代理类调用的所有的方法都变了 h.invoke(proxy,method,args)调用方法,而在invoke 中又知道了方法的method ,即让方法调用对象 method.invoke(target,args)
 * 		因为代理类始终是自己,所以就变成了h.inovoke(this,method,args)
 * 
 * */

下面是反编译得到的动态类,实现Comparable 接口

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class Proxy0 extends Proxy
  implements Comparable
{
  private static Method m3;
  private static Method m1;
  private static Method m0;
  private static Method m2;

  public Proxy0()
    throws 
  {
    super(paramInvocationHandler);
  }

  public final int compareTo()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m3, new Object[] { paramObject })).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final boolean equals()
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return ((String)this.h.invoke(this, m2, null));
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  static
  {
    try
    {
      m3 = Class.forName("java.lang.Comparable").getMethod("compareTo", new Class[] { Class.forName("java.lang.Object") });
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}



 

相关文章推荐

Java 动态代理实现解析

Java动态代理只能针对接口进行动态代理。如果需要对类进行实现代理可以使用:CGLIB,ASM等相关的操作字节码实现(在这里先只介绍下SUN 基于接口动态代理的实现)。 代码如下: import ja...

JDK动态代理实现原理

地址:http://rejoy.iteye.com/blog/1627405 之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白。比如说:InvocationHandler的invoke方...

JDK-Proxy示例

JDK 从1.3开始提供的 Proxy 工具类, 以提供用代理的方式去执行某个接口的某些方法, 在Spring AOP的实现中就有应用;...

ProxyGenerator

/* * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COP...
  • xlnjulp
  • xlnjulp
  • 2014年06月25日 21:03
  • 593

.Net动态代理Castle ( 了解创建动态代理 )

什么是动态代理?想很好的了解动态代理,就需先来了解代理的概念,代理 (Proxy)这个概念在现实生活中无处不在,比如房屋中介,它就是一个代理对象, 能代理行驶房东(可以理解为Target)的权力,...

JDK中的proxy动态代理

动态代理的原理: 1. proxy0继承Proxy,实现IPackageManager 接口,需要传入 InvocationHandler,初始化对应的h对象。 2. 我们的h对象就是Pa...

导入某些特殊Jar包中的类

导入特殊jar设置 在通常的开发中可能会去看下API的源代码,自己有时候也可以模仿API中的源代码做一些研究,可是有些特殊jar包中的类报无法导入的错误: The import sun.misc....

JD-GUI反编译后代码逻辑分析

一,用jd-gui.exe等工具查看源代码。如何你不会,可以参看此文章: http://blog.csdn.net/hp_2008/article/details/8207879  可...

反编译与反汇编

反编译做的就是编译的相反动作。举例来说,例如一个程序用C语言来写,写完之后要编译成CPU可以识别和运行的机器代码,也就是生成EXE程序。而反编译是反过来,把EXE反编译成编程源代码,也就是C程序,不过...

Java 动态代理源码分析

Java 动态代理 本文为 Android 开源项目源码解析 公共技术点中的 动态代理 部分 项目地址:Jave Proxy,分析的版本:openjdk 1.6,Demo 地址:Proxy...
  • jQuerys
  • jQuerys
  • 2015年08月31日 17:04
  • 1809
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Proxy 动态代理再次理解
举报原因:
原因补充:

(最多只允许输入30个字)