所谓动态代理,就是在程序运行的时候,JVM能动态的知道它要对哪个类的哪些方法进行代理,以此实现程序的可重用性,也减少了程序员的劳动量。
一个动态代理必须要有的四个类:一个接口,一个实现了该接口的类,一个实现InvocationHandler接口的类,再就是写一个有main方法的测试类。这里需要重点说的是实现了InvocationHandler接口的类,在InvocationHandler接口里有且只有一个方法:invoke(),真正的代理是由此方法来实现的,它需要三个参数:要代理的类,要代理的方法,以及方法的参数(可参照jdk1.5中的写法:Object invoke(Object proxy,Method method,Object[] args)throws Throwable,要代理的真实类可以用一个构造函数来接收)。所以实现了InvoactionHandler接口的类必须实现invoke()这个方法,在这个方法里我们可以利用反射的原理调用指定类的具有指定参数的方法,也就是实现代理。
程序清单如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.logging.Logger;
public class LogHandler implements InvocationHandler
{
private Logger log=Logger.getLogger(this.getClass().getName());
private Object delegate;
public LogHandler(Object delegate)
{
this.delegate=delegate;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
{
Object obj=null;
try
{
log.info("method stats...."+method);
obj=method.invoke(delegate,args);
log.info("method end...."+method);
}
catch(Exception e)
{
log.info("Exception happends....");
}
return obj;
}
}
另外一个需要说的就是有main()方法的测试类,在这个main()方法里我们需要用真实类创建一个对象,并以此对象为参数实例化一个InvocationHandler(参考jdk1.5中的写法:InvocationHandler handler = new MyInvocationHandler(...)),最核心的一步就是用Proxy类得到一个接口类的代理类(参考jdk1.5中的写法:Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class },handler);其中Foo是原始类,即被代理的类),用这个代理类来调用原始类中的方法(它是通过invoke()方法实现的),至此我们就完成了动态代理。
测试类程序清单如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class BusinessObject
{
public static void main(String args[])
{
BussObj businessImp=new BussObj();
InvocationHandler handler=new LogHandler(businessImp);
Business business=(Business)Proxy.newProxyInstance(Business.class.getClassLoader(),businessImp.getClass().getInterfaces(),handler);
business.getString();
}
}
说明:Business是接口,BussObj类是实现了Business接口的类,这两个类中的代码需要读者自己去写!
程序运行结果如下