黑马程序员 动态代理

------------------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培训期待与您交流!-------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值