从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()方法.在hello方法中,调用父类Proxy中的h的invoke()方法,即InvocationHandler.invoke();方法。