Java Proxy学习总结

来源:互联网 发布:mac怎么循环播放视频 编辑:程序博客网 时间:2024/06/07 05:44

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

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

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

public class JdkDbQueryHandler implements InvocationHandler{private IDBQuery real = null;    //主题接口实例public JdkDbQueryHandler(IDBQuery real)  //会传递一个真实主题的对象{this.real = real;}/** * 参数method代表动态代理实例中被调用的方法 */@Overridepublic 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
原创粉丝点击