Spring AOP基础—JDK动态代理
JDK动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。其中InvocationHandler动态创建一个符合某一接口的实例,生成目标类的代理对象。
首先写一个接口 ForumService.java 及其实现类 ForumServiceImpl.java ,主要包括二个方法,删除主题removeTopic 和 删除 removeForum。代码如下:
public class ForumServiceImpl implements ForumService {
@SuppressWarnings("static-access")
public void removeForum(int forumId) {
System.out.println("模拟删除Forum记录:" + forumId);
try {
Thread.currentThread().sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@SuppressWarnings("static-access")
public void removeTopic(int topicId) {
System.out.println("模拟删除Topic记录:" + topicId);
try {
Thread.currentThread().sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
现在需要对二个方法的执行效率进行监控,所以创建一个监控方法效率的类 PerformanceMonitor.java 和 一个辅助工具类 MethodPerformance.java。代码如下:
public class MethodPerformance {
private long begin;
private long end;
private String serviceMethod;
public MethodPerformance(String serviceMethod){
this.serviceMethod = serviceMethod;
this.begin = System.currentTimeMillis();
}
public void printPerformance(){
end = System.currentTimeMillis();
long elapse = end - begin;
System.out.println(serviceMethod + "花费" + elapse + "毫秒");
}
}
public class PerformanceMonitor {
private static ThreadLocal<MethodPerformance> performanceRecord = new ThreadLocal<MethodPerformance>();
public static void begin(String method){
System.out.println("begin monitor……");
MethodPerformance mp = new MethodPerformance(method);
performanceRecord.set(mp);
}
public static void end(){
System.out.println("end monitor……");
MethodPerformance mp = performanceRecord.get();
mp.printPerformance();
}
}
为了将监控方法效率的代码织入到业务方法 removeTopic 和 removeForum中,我们创建代理类 PerformanceHandler.java,代码如下:
public class PerformanceHandler implements InvocationHandler {
private Object target;
public PerformanceHandler(Object target) {
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
PerformanceMonitor.begin(target.getClass().getName() + "." + method.getName());
Object obj = method.invoke(target, args);
PerformanceMonitor.end();
return obj;
}
}
首先,我们实现InvocationHandler接口,该接口定义了一个invoke(Object proxy,Method method,Object[] args)方法,proxy是最终生成的代理实例,一般不会用到;method是被代理目标实例的某个具体方法,通过它可以发起目标实例方法的反射调用;args是通过被代理实例某一个方法的入参,在方法 反射调用时使用。
此外,我们再构造函数里通过target传入希望被代理的目标对象,在InvocationHandler()接口方法invoke(Object proxy,Method method,Object[] args)里,将目标实例传给method.invoke()方法,调用目标实例的方法。
下面,我们通过Proxy结合PerformanceHandler创建ForumService接口的代理实例,这个代理实例实现了目标业务类的所有接口,即ForumServiceImpl的ForumService接口。这样我们就可以按照调用ForumService接口实例相同的方式调用代理实例。代码如下:
public class TestForumService {
public static void main(String[] args) {
ForumService target = new ForumServiceImpl();
PerformanceHandler handler = new PerformanceHandler(target);
ForumService proxy = (ForumService) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handler);
proxy.removeForum(1001);
proxy.removeForum(100);
}
}
执行结果如下:
begin monitor……
模拟删除Forum记录:1001
end monitor……
com.aop.ForumServiceImpl.removeForum花费16毫秒
begin monitor……
模拟删除Forum记录:100
end monitor……
com.aop.ForumServiceImpl.removeForum花费15毫秒
浙公网安备 33010602011771号