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...
  • kevin_Luan
  • kevin_Luan
  • 2014年04月06日 16:53
  • 3814

JDK动态代理实现原理

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

JDK中的proxy动态代理

动态代理的原理: 1. proxy0继承Proxy,实现IPackageManager 接口,需要传入 InvocationHandler,初始化对应的h对象。 2. 我们的h对象就是Pa...
  • chenzhiqin20
  • chenzhiqin20
  • 2016年03月15日 22:01
  • 2962

android 使用代码,自动设置代理IP

1. 此例子以Android 4.2.2,  API 17为基础。 2. 后面 Android 5.0.1,  API 21 设置又不一样。 // 设置公共成员常量值  public st...
  • chentaoxie
  • chentaoxie
  • 2016年08月24日 11:16
  • 4726

webservice如何设置代理服务

proxyProperties.setProxyName(config.getValue("host")); proxyProperties.setProxyPort(In...
  • bestcxx
  • bestcxx
  • 2016年05月13日 13:54
  • 1972

Java工具类---资源文件解析类 PropertiesUtil

package com.luang.util.properties; import java.io.File; import java.io.FileInputStream; impo...
  • jibaole
  • jibaole
  • 2016年08月04日 09:44
  • 2508

【转】Java工具类——资源文件解析类PropertiesUtil

处理Properties文件的另一更佳解决方案:见http://blog.csdn.net/softwave/article/details/6873227《Java的Properties文件操作类》...
  • softwave
  • softwave
  • 2013年04月14日 10:38
  • 9846

读取properties配置文件的工具类

一般小工程,properties配置文件之间在src根目录创建 比如data.properties,代码如下 PROXY=192.168.0.1 PORT=8080 USERNAME=use...
  • sdsky1987
  • sdsky1987
  • 2012年04月01日 10:20
  • 7284

Java读取Properties文件工具类

读取properties文件工具类package zmx.util; import java.io.InputStream; import java.util.Properties; /** * ...
  • zmx729618
  • zmx729618
  • 2016年04月13日 16:05
  • 1963

读取properties文件,工具类。

我们通常都会遇到需要解析properties文件内容的需求,下面就贴上读取properties文件属性的工具类  与  调用方法 解析properties工具类 import java.io....
  • shasiqq
  • shasiqq
  • 2016年05月30日 10:21
  • 1361
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Proxy 动态代理再次理解
举报原因:
原因补充:

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