首先,自己实现AOP。
本Demo的目的是要实现调用每个目标方法时,启用方法的性能监控,在目标类方法调用完成时记录方法花费的时间。
1. 先定义接口文件
package com.hik.aopImpl.proxy;
public interface ForumService {
public void removeTopic(int topicId);
public void removeForum(int forum);
}
2. 实现类代码:
package com.hik.aopImpl.proxy;
public class ForumServiceImpl implements ForumService{
public void removeTopic(int topicId) {
//1 开始对该方法进行性能监控
PerformaceMontior.begin("com.hik.aopImpl.proxy.ForumServiceImpl.removeTopic");
System.out.println("模拟删除Topic记录:" + topicId);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//2 结束对该方法进行性能监控
PerformaceMontior.end();
}
public void removeForum(int forumId) {
//1 开始对该方法进行性能监控
PerformaceMontior.begin("com.hik.aopImpl.proxy.ForumServiceImpl.removeForum");
System.out.println("模拟删除Forum记录:" + forumId);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//2 结束对该方法进行性能监控
PerformaceMontior.end();
}
}
3. 性能监视实现类文件:
package com.hik.aopImpl.proxy;
public class PerformaceMontior {
private static ThreadLocal<MethodPerformace> PerformaceMontior = new ThreadLocal<MethodPerformace>();//通过创建一个ThreadLocal保存调用线程相关的性能监视信息
public static void begin(String method) {
System.out.println("Begin Montior ....");
MethodPerformace mp = new MethodPerformace(method);
PerformaceMontior.set(mp);
}
public static void end() {
System.out.println("end Montior ....");
MethodPerformace mp = PerformaceMontior.get();
mp.printPerformace();
}
}
package com.hik.aopImpl.proxy;
public class MethodPerformace {
private long begin;
private long end;
private String serviceMethod;
public MethodPerformace(String serviceMethod) {
this.begin = System.currentTimeMillis();
this.serviceMethod = serviceMethod;
}
public void printPerformace() {
this.end = System.currentTimeMillis();
System.out.println(serviceMethod + "一共花费了" + (end - begin) + "毫秒。");
}
}
4. 测试:
package com.hik.aopImpl.proxy;
import java.lang.reflect.Proxy;
public class TestForumService {
public static void main(String[] args) {
ForumService f = new ForumServiceImpl();
f.removeForum(10);
f.removeTopic(1012);
}
}
运行结果:
JDK动态代理
package com.hik.aopImpl.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class PerformanceHandler implements InvocationHandler {
private Object target;
public PerformanceHandler(Object target) {
super();
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
PerformaceMontior.begin(target.getClass().getName() + "." + method.getName());
Object obj = method.invoke(target, args);
PerformaceMontior.end();
return obj;
}
}
相应的,更新测试代码:package com.hik.aopImpl.proxy;
import java.lang.reflect.Proxy;
public class TestForumService {
public static void main(String[] args) {
ForumService f = new ForumServiceImpl();
PerformanceHandler ph = new PerformanceHandler(f);
ForumService proxy = (ForumService) Proxy.newProxyInstance(f.getClass().getClassLoader(), f.getClass().getInterfaces(), ph);
proxy.removeForum(10);
proxy.removeTopic(1012);
}
}
NOTE: JDK 动态代理技术只能使用于有接口,对于没有接口的方法,则只能使用、CGLib代理。
CGLib动态代理
package com.hik.aopImpl.proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
public Object getProxy(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
return enhancer.create();
}
public Object intercept(Object obj, Method method, Object[] arg,
MethodProxy proxy) throws Throwable {
PerformaceMontior.begin(obj.getClass().getName() + "." + method.getName());
Object result = proxy.invokeSuper(obj, arg);
PerformaceMontior.end();
return result;
}
}
更新测试类:
package com.hik.aopImpl.proxy;
import java.lang.reflect.Proxy;
public class TestForumService {
public static void main(String[] args) {
ForumService f = new ForumServiceImpl();
CglibProxy cg = new CglibProxy();
ForumServiceImpl proxy = (ForumServiceImpl) cg.getProxy(ForumServiceImpl.class);
proxy.removeForum(10);
proxy.removeTopic(1012);
}
}