Java动态代理我之理解

参考:Spring开发指南(作者:夏昕)

-------------------------------------------------------------------------------------------------------------------------------

在Spring开发指南(作者:夏昕)的论述中提到了Java的动态代理,按照作者的说法,Dynamic Proxy是JDK 1.3版本中新引入的一种动态代理机制。它是Proxy模式的一种动态实现版本。

下面,用代码来说明一下Java动态代理。

首先,被代理的类必须是实现某个接口的。我们现在定义接口——计算器接口:

 

package test.quqtalk.dynamicproxy;
/**
 * 计算器接口
 * @author Administrator
 *
 */
public interface CalculatorInterface {
	public int add(int arg1, int arg2);
}

然后,是接口的实现——计算器: 

 

package test.quqtalk.dynamicproxy;
/**
 * 计算器实现
 * @author Administrator
 *
 */
public class CalculatorImpl implements CalculatorInterface {
	/**
	 * 返回两个整数的和
	 */
	public int add(int arg1, int arg2) {
		return arg1 + arg2;
	}
}

 

最后,是代理的实现。这里需要实现InvocationHandler接口,假设我们这个代理的作用是在调用add函数前后记录时间点。我们叫LogHandler。

 

package test.quqtalk.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 计算器代理
 * 
 * @author Administrator
 * 
 */
public class LogHandler implements InvocationHandler {
	Log log = LogFactory.getLog(LogHandler.class);
	SimpleDateFormat sdf= new SimpleDateFormat("yyyy-dd-MM hh:mm:ss");
	Object obj_orgin;

	/**
	 * 传入被代理对象,返回代理对象
	 * 
	 * @param obj,被代理对象
	 * @return 代理对象
	 */
	public Object bind(Object obj) {
		this.obj_orgin = obj;
		return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
				.getClass().getInterfaces(), this);
	}

	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {

		if (method.getName().equals("add")) {
			int ret = 0;
			// 在invoke前记录日志
			log.info("before add time is " + sdf.format(new Date()));
			ret = (Integer) method.invoke(obj_orgin, args);
			// 在invoke后记录日志
			log.info("after add time is " + sdf.format(new Date()));
			return ret;
		} else {
			return method.invoke(obj_orgin, args);
		}
	}
	
}

 

测试main函数:

 

	public static void main(String[] args) {
		CalculatorInterface c = (CalculatorInterface) new LogHandler()
				.bind(new CalculatorImpl());
		System.out.println("result is " + c.add(1, 1));
	}
 

控制台输出结果:

16:59:38,531 INFO  [main] test.quqtalk.dynamicproxy.LogHandler (LogHandler.java:41) - before add time is 2009-13-05 04:59:38

16:59:38,531 INFO  [main] test.quqtalk.dynamicproxy.LogHandler (LogHandler.java:44) - after add time is 2009-13-05 04:59:38

result is 2


当然,这个例子是非常简单的,在项目中这样做基本没有什么实用价值。然而通过这个例子,基本可以明白动态代理的机制和好处。
如果有很多个函数都需要在调用前和调用后记录时间点,那么只需要将这些对象传入 LogHandler的bind函数,用得到的代理调用相应函数即可。当然,这里不只可以记录日志,我们可以做任意我们想做的事情。我想这就是动态代理的好处。

 

 

 

 

 

 

你可能感兴趣的:(java,apache,spring,jdk,c)