------------------android培训、 java培训、期待与您交流!-------------------
什么是动态代理,张老师首先举了一个生活中的例子。如某武汉客户买联想电脑,那他通常会选择在武汉当地的联想代理商店购买,而不是直奔北京总部,这样就省了很多事儿。而程序中为什么要用动态代理呢?如果我们需要在正常的业务方法执行的前后添加一点小功能,例如统计某业务处理花费的时间(在程序中业务处理会抽象成具体的方法),那么我们就需要在方法执行前后添上获取系统当前时间的功能。代理类和目标类继承同一个接口,现在客户端调用只需要调用代理类对象,执行目标类的方法,就能实现此前的辅助功能。实现动态代理,最重要的就是Proxy和InvocationHandler。代理类必须先实现InvocationHandler接口,重写其invoke方法。在invoke方法中,通过反射调用业务方法,统计时间的功能也在invoke中实现。先来看一个InvocationHandler的实现类。
public class ChildHandler implements InvocationHandler {
private Object targetObj;//目标对象
public ChildHandler(Object tObject)
{
targetObj=tObject;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//计时开始
TimeCountUitl.timeBegin();
Object obj=method.invoke(targetObj, args);
//method的invoke方法返回方法执行的返回值
// 计时结束
TimeCountUitl.timeEnd();
return obj;
}
利用InvocationHandler的实现类,就可以用工厂类产生对应目标类的动态代理对象。
/**
*动态代理工厂,生成代理对象
*/
public class ProxyFactory {
public static Object generateProxy(Object targetObj)
{
ChildHandler handler=new ChildHandler(targetObj);
Object proxy=Proxy.newProxyInstance(targetObj.getClass().getClassLoader(), targetObj.getClass().getInterfaces(), handler);
return proxy;
}
}
前面用到的计时工具类非常简单。
/**
*计时工具类
*/
public class TimeCountUitl {
private static long timeStart;
//计时开始
public static long timeBegin()
{
timeStart=System.currentTimeMillis();
return timeStart;
}
public static void timeEnd()
{
long time=(System.currentTimeMillis()-timeStart)/1000;
System.out.println("吃饭用时:"+time+"s");
}
}
目标类Child是一个接口,Jobs是其实现类,只包含一个吃饭的方法。吃饭耗时用了线程休眠来模拟。
public interface Child {
void eat();//孩子吃饭的方法
}
public class Tom implements Child {
public void eat() {
System.out.println("Tom开始吃饭。");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Tom吃完飯了。");
}
}
现在,基础结构已经建好了。就差一个客户端来调用动态代理对象了。这里我把客户端模拟成了一个管理孩子吃饭的监管者。他专门负责管理孩子吃饭,也是他要求要统计孩子的吃饭时间。现在他要看效果了。
/**
* 监管孩子吃饭的管理者类
*/
public class Supervisor {
public static void main(String[] args)
{
Child target=new Tom();//目标类对象
Child child=(Child)ProxyFactory.generateProxy(target);
child.eat();//代码1
}
}
当然,监管者能够达到目的。从代码1可以看到,同样是一个Child对象,执行的却是InvocationHandler的实现类的invoke方法。也就达到了我们添加辅助功能的目的。这也是添加动态代理的意义所在。
------------------android培训、 java培训、期待与您交流!-------------------