从JDK1.3以后,java引入动态代理机制,即对目标对象的方法调用是通过代理对象来完成的,java的动态代理只能针对接口进行动态代理,即要实现动态代理的类必须实现接口,CGLIB提供了针对类的动态代理功能。JDK动态代理的例子如下:
//代理接口 package com.proxy.test; interface IProxy{ public void hello(String s); } //接口实现类,即被代理类 class ProxyImpl implements IProxy { public void hello(String s){ System.out.println(“Hello, ” + s); } } //动态代理处理类 class ProxyHandler implements InvocationHandler{ //代理实现类 private Object delegate; public ProxyHandler (Object obj) { delegate = obj; } public Object invoke(Object proxy, Method method, Object[] args){ System.out.println(“Before mothod:” + method); Object result = method.invoke(this.delegate, args); System.out.println(“After mothod:” + method); return result; } } public class DynamicProxyDemo{ public static void main(String[] args){ IProxy p = new ProxyImpl(); ProxyHandler handler = new ProxyHandler(p); //产生动态代理 IProxy proxy = (IProxy)Proxy.newProxyInstance(IProxy.class.getClassLoader(), p.getClass().getInterfaces(), handler); proxy.hello(“world”); } }
输出结果:
Before mothod:hello
Hello, world
After mothod:hello
相信很多人都会写上面的动态代理,但是很多人对下面的问题感觉迷惑不解:
(1).InvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法中proxy参数并没有在方法体内使用,这个参数到底被谁使用?
这个问题比较好回答,proxy虽然没有在invoke方法体内使用,但是这个参数就是Proxy.newProxyInstance方法产生的动态代理对象,通过这个代理对象做如下两件事:
a.在调用目标对象之前/之后首先调用InvocationHandler的Invoke方法。
b.代理对象调用目标对象的目标方法。
(2).Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)方法究竟做了什么事?
Proxy.newProxyInstance方法返回了一个实现代理接口,并且代理了目标方法实例行为的对象,通过JDK中sun.misc.ProxyGenerator.generateProxyClass()方法操作字节码完成以下几件事.
a.根据类加载器参数loader和代理接口interfaces调用方法 getProxyClass(loader, interfaces)创建代理类$Proxy.
$Proxy0类实现了interfaces的接口,并继承了Proxy类.
b.实例化$Proxy0并在构造方法中把实现了InvocationHandler接口的代理处理器对象传给父类Proxy,接着$Proxy0调用父类Proxy的构造器,为h赋值。
在程序中通过System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”,“ture”);设置java虚拟机系统属性,在运行程序的过程中会生成$Proxy0.class文件,使用反编译工具反编译之后代码如下:
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 IProxy { private static Method m0; private static Method m1; private static Method m2; private static Method m3; static { try { //通过反射机制获取Object中的hashCode(), equals()和toString()方法 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); //获取代理接口Proxy的代理方法hello m3 = Class.forName("com.proxy.test.IProxy").getMethod("hello", new Class[0]); } catch (NoSuchMethodException nosuchmethodexception) { throw new NoSuchMethodError(nosuchmethodexception.getMessage()); } catch (ClassNotFoundException classnotfoundexception) { throw new NoClassDefFoundError(classnotfoundexception.getMessage()); } } //将实现了InvocationHandler接口的对象传递给父类Proxy public $Proxy0(InvocationHandler invocationhandler) { super(invocationhandler); } //代理hashCode()方法 @Override public final int hashCode() { try { return ((Integer) super.h.invoke(this, m0, null)).intValue(); } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } //代理equals()方法 @Override public final boolean equals(Object obj) { try { return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue(); } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } //代理toString()方法 @Override public final String toString() { try { return (String) super.h.invoke(this, m2, null); } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } //代理接口中的代理方法 public final void hello() { try { super.h.invoke(this, m3, null); return; } catch (Error e) { } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } }当执行 proxy.hello() 方法时 , 就调用了 $Proxy0 类中的 hello() 方法 .