Java Proxy学习总结

昨天看了JDK动态代理实现,不是很明白,想知道代理类是怎么实现的,它里面有哪些成员和方法,为什么调用InvocationHandler的invoke方法会得到自动调用。带着这些问题我在网上查阅了资料,现在将自己所理解的JDK动态代理整理一下。

1.先来看下动态代理实现中需要的关键类和方法

     1)一个处理方法调用的Handler

public class JdkDbQueryHandler implements InvocationHandler
{
	private IDBQuery real = null;    //主题接口实例

	public JdkDbQueryHandler(IDBQuery real)  //会传递一个真实主题的对象
	{
		this.real = real;
	}
	
	/**
	 * 参数method代表动态代理实例中被调用的方法
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable
	{
		Object result = method.invoke(real, args);
		
		return result;
	}
}

      2)一个生成代理类实例$Proxy0的方法

// 使用JDK的动态代理生成代理对象
public static IDBQuery createJdkProxy()
{
	IDBQuery jdkProxy = (IDBQuery) Proxy.newProxyInstance(
	        ClassLoader.getSystemClassLoader(),
		new Class[] { IDBQuery.class }, new JdkDbQueryHandler());

	return jdkProxy;
}

那么,当我们调用createJdbProxy()方法得到代理类实例,即调用Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)这个方法时发生了什么了?

          a)调用Proxy的newProxyInstance()方法后,首先根据loader和interfaces两个参数得到实现interfaces接口且继承Proxy类的Class对象c1

          b)接着调用c1的getConstructor(Class<?>... parameterTypes)方法,InvocationHandler.class作为参数得到Constructor对象

          c)调用Constructor的Object newInstance(Constructor<?> cons, InvocationHandler h),在该方法中调用cons.newInstance(new Object[]{h})方法生成代理类的实例(此时调用了父类Proxy的构造方法Proxy(InvocationHandler h)为Proxy中的属性InvocationHandler赋值)。并且用interfaces参数遍历其所有接口的方法,并生成Method对象初始化代理类中的几个Method成员变量.

          d)通过传入的第一个参数classloder将刚生成的类加载到jvm中。


2.调用关系

当我们通过createJdkProxy()方法得到代理类的实例且调用interfaces接口中的某个方法时,比如代理类q调用了request()方法,在代理类重写接口的方法request()中有这么一条语句 super.h.invoke(this, m3, null); 到这里相信大家都会明白了,也就是说,当我们调用代理类中的方法时,会调用父类Proxy的InvocationHandler类型属性的invoke(Object proxy,Method method,Object[] args)方法,也就是JdkDbQueryHandler中的invoke()方法。


从上面的分析中可知InvocationHandler中的invoke()方法参数Object proxy其实就是我们生成的代理类对象,但是为什么在JdkDbQueryHandler的invoke()方法中我们没有使用该对象而是使用真实主题的对象了?假如我们就使用proxy对象。我们来分析下:首先,我们是调用了代理类$Proxy0的request()方法,在该方法中调用了InvocationHandler的invoke()方法,如果InvocationHandler的invoke方法写成method.invoke(proxy, args); 这就是调用代理类的method对象所指定,也就是request方法,那此时是不是又调用了InvocationHandler的invoke()方法,这样就会进入死循环。解决的办法是使用我给的实例代码这种写法,传递一个真实主题的实例,那么当method.invoke(real, args);时,就会调用真实主题的method所对应的方法。


本文整理资料来自于:

http://blog.csdn.net/rokii/article/details/4046098

http://hi.baidu.com/malecu/item/9e0edc115cb597a1feded5a0




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值