29,高新技术——动态代理
29.1 代理的作用
为目标类增加一些辅助功能.
示意图:
29.2 创建动态代理类的对象
由于目标类是任意的,如何才能很方便的创建任意一个目标类的代理对象,可以调用java.lang.reflect.Proxy类中的静态方法:
public static Object newProxyInstance(ClassLoader loader,Class<?>[]interfaces,InvocationHandler h)throws IllegalArgumentException
此方法需要三个参数:
loader -代理类的类加载器
interfaces - 代理类要实现的接口列表(与目标类实现的接口相同,由于接口可以多实现,所以这里是一个数Class数组).
h - 指派方法调用的调用处理程序
如:创建一个目标类:ArrayList的代理.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
public class ProxyDemo {
public static void main(String[]args) {
//创建代理类的对象.
Collection coll=(Collection)Proxy.newProxyInstance(
Collection.class.getClassLoader(),
new Class[]{Collection.class},
new InvocationHandler(){//用匿名内部类的形式创建InvocationHandler的子类对象,并覆盖其内部方法.
ArrayList al=new ArrayList();//创建目标类对象.
@Override
public Object invoke(Object proxy, Method method,Object[] args)throws Throwable {
//需要增加的辅助功能.
long begintime=System.currentTimeMillis();
//调用目标类的方法.
Object retVal=method.invoke(al, args);
//需要增加的辅助功能.
long costtime= System.currentTimeMillis()-begintime;
System.out.println(costtime);
return retVal;
}});
coll.add("abc");
coll.add("abc");
coll.add("abc");
System.out.println(coll.size());
}
}
InvocationHandler中的invoke()方法,也接收了三个参数,为什么要接收这几个参数呢?
public Object invoke(Object proxy, Method method,Object[] args)throws Throwable
通过Proxy类的newInstance()方法,可以创建任意代理类的对象,当代理类执行一次目标类中的方法时,就会执行一次传入的InvocationHandler参数中的invoke()方法.
proxy接收代理类的对象,method接收的是代理类所执行的方法,args则表示代理类对象所调用的方法所传入的参数.
从上面的代码中可以看出,目标类的对象是在程序中自己new的,功能代码也需要自己写进去的,由于目标类和辅助功能代码的不确定性,可见代码的通用性较差.
如何能够动态的创建代理类对象?
可以将,目标类和辅助功能封装成对象以参数的形式传递给InvocationHandler.
如:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
public class ProxyDemo {
public static void main(String[] args) {
ArrayList al=new ArrayList();//创建目标类的对象.
Collection coll=(Collection)new GetProxyClass().getProxy(al,new MyAdvice());
coll.add("abc");
coll.add("abc");
coll.add("abc");
System.out.println(coll.size());
}
}
class GetProxyClass{//定义获取代理类对象的类.
private Objecttarget;
private Adviceadvice;
public Object getProxy(final Object target,final Advice advice){//将目标对象和辅助功能作为参数传递给方法getProxy.
Object proxy=Proxy.newProxyInstance(
target.getClass().getClassLoader(),//获取代理类的类加载器.
target.getClass().getInterfaces(),//获取代理类的实现接口.
new InvocationHandler(){//创建 InvocationHandler的子类对象,并覆盖方法.
@Override
public Object invoke(Object proxy, Method method,
Object[] args)throws Throwable {
advice.beforeMethod();//使用辅助功能.
Object retVal=method.invoke(target, args);
advice.afterMethod();//使用辅助功能.
return retVal;
}});
return proxy;
}
}
interface Advice{//定义接口,提高程序的扩展性.
void beforeMethod();
void afterMethod();
}
class MyAdvice implements Advice{//辅助功能实现接口.
private long begintime;
private long endtime;
//定义辅助功能
@Override
public void beforeMethod() {
begintime=System.currentTimeMillis();
}
//定义辅助功能
@Override
publicvoid afterMethod() {
endtime=System.currentTimeMillis();
System.out.println(endtime-begintime);
}
}
由此可见,通过动态代理可以对任意目标类完成辅助功能的添加.
---------------------- ASP.Net+Android+IOS开发、 .Net培训、期待与您交流! ----------------------