Java动态代理(优点不修改源码的情况下,扩展加强方法,AOP编程)
代码结构(dynamic部分):
还是使用上期的卖房接口
package com.xingsfdz.proxy;
/**
*
* @类名称 SellHouse.java
* @类描述 <pre>卖房接口</pre>
* @作者 xingsfdz xingsfdz@163.com
* @创建时间 2019年5月6日 下午10:40:31
* @版本 1.00
*
* @修改记录
* <pre>
* 版本 修改人 修改日期 修改内容描述
* ----------------------------------------------
* 1.00 xingsfdz 2019年5月6日
* ----------------------------------------------
* </pre>
*/
public interface SellHouse {
void sell();//提供一个卖的方法
}
被代理对象:
package com.xingsfdz.proxy.dynamic;
import com.xingsfdz.proxy.SellHouse;
/**
*
* @类名称 Owner.java
* @类描述 <pre>动态代理-被代理对象(实际执行操作的类)</pre>
* @作者 xingsfdz xingsfdz@163.com
* @创建时间 2019年5月7日 下午9:58:39
* @版本 1.00
*
* @修改记录
* <pre>
* 版本 修改人 修改日期 修改内容描述
* ----------------------------------------------
* 1.00 xingsfdz 2019年5月7日
* ----------------------------------------------
* </pre>
*/
public class Owner implements SellHouse {
@Override
public void sell() {
//业主考虑了5秒
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("业主卖房...");
}
}
代理对象(核心实现jdk的InvocationHandler接口,原理反射):
package com.xingsfdz.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
*
* @类名称 Proxy.java
* @类描述 <pre>动态代理需要实现的接口(JDK) -- 最关键的 实现接口InvocationHandler</pre>
* @作者 xingsfdz xingsfdz@163.com
* @创建时间 2019年5月7日 下午10:08:58
* @版本 1.00
*
* @修改记录
* <pre>
* 版本 修改人 修改日期 修改内容描述
* ----------------------------------------------
* 1.00 xingsfdz 2019年5月7日
* ----------------------------------------------
* </pre>
*/
public class Agent<T> implements InvocationHandler {
T target;//被代理的对象
//有参构造
public Agent(T target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//代理过程中插入监测方法,计算该方法耗时
MonitorUtil.start();//aop编程
Object result = method.invoke(target, args);//代理对象执行被代理对象方法的具体操作
MonitorUtil.finish(method.getName());//aop编程
return result;
}
}
时间检测方法:
package com.xingsfdz.proxy.dynamic;
/**
*
* @类名称 MonitorUtil.java
* @类描述 <pre>检测执行时间方法</pre>
* @作者 xingsfdz xingsfdz@163.com
* @创建时间 2019年5月7日 下午10:04:34
* @版本 1.00
*
* @修改记录
* <pre>
* 版本 修改人 修改日期 修改内容描述
* ----------------------------------------------
* 1.00 xingsfdz 2019年5月7日
* ----------------------------------------------
* </pre>
*/
public class MonitorUtil {
private static ThreadLocal<Long> tl = new ThreadLocal<>();
//开始时间
public static void start() {
tl.set(System.currentTimeMillis());
}
//结束时间
public static void finish(String methodName) {
long finishTime = System.currentTimeMillis();
System.out.println(methodName + "方法耗时" + (finishTime - tl.get()) + "ms");
}
}
测试验证:
package com.xingsfdz.proxy.dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import com.xingsfdz.proxy.SellHouse;
/**
*
* @类名称 Test.java
* @类描述 <pre>动态代理测试</pre>
* @作者 xingsfdz xingsfdz@163.com
* @创建时间 2019年5月7日 下午10:15:00
* @版本 1.00
*
* @修改记录
* <pre>
* 版本 修改人 修改日期 修改内容描述
* ----------------------------------------------
* 1.00 xingsfdz 2019年5月7日
* ----------------------------------------------
* </pre>
*/
public class Test {
public static void main(String args []) {
//创建一个被代理对象的实例对象
SellHouse ow = new Owner();
//创建一个与代理对象相关联的InvocationHandler
InvocationHandler owHandler = new Agent<SellHouse>(ow);//告诉owHandler 是T类型 SellHouse
//创建一个代理对象agent来代理ow,代理对象的每个执行方法都会替换执行Invocation中的invoke方法。此处是传入接口SellHouse 动态生成代理对象agent
//java.lang.reflect.Proxy:该类用于动态生成代理类,只需传入目标接口的类加载器、目标接口以及InvocationHandler便可为目标接口生成代理类及代理对象
//Object java.lang.reflect.Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
SellHouse agent = (SellHouse) Proxy.newProxyInstance(SellHouse.class.getClassLoader(), new Class<?>[]{SellHouse.class}, owHandler);
agent.sell();//动态创建的代理对象执行sell
}
}
运行结果:
业主卖房...
sell方法耗时5001ms