首先,自己實現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);
}
}