這一主要看看Spring AOP是如何實作通知包圍的。
Spring AOP包圍通知在功能上和前置通知加後置通知類似,但還是有差別的:包圍通知可以修改傳回值,還可以阻止、替換目标方法的執行。
Spring裡的包圍通知是實作MethodInterceptor接口的攔截器。
Spring包圍通知有着很廣泛的應用,比如遠端代理和事務管理,都是由攔截器完成。另外,攔截器也是剖析程式運作的好方法。
下面利用Spring AOP包圍通知實作監控業務方法的執行運作過程耗時情況。
/**
* 業務元件
*/
public class WorkerBean {
public void doSomeWork(int noOfTimes) {
for(int x = 0; x < noOfTimes; x++) {
work();
}
}
private void work() {
System.out.print("");
}
}
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.util.StopWatch;
/**
* 攔截器,實作方法包圍通知
*/
public class ProfilingInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation invocation) throws Throwable {
//啟動一個 stop watch
StopWatch sw = new StopWatch();
//運作計時器
sw.start(invocation.getMethod().getName());
//執行業務方法
Object returnValue = invocation.proceed();
//停止計時器
sw.stop();
//垃圾資訊輸出
dumpInfo(invocation, sw.getTotalTimeMillis());
//傳回業務方法傳回值
return returnValue;
}
/**
* 垃圾資訊輸入方法,實際上輸出的是方法運作的計時資訊
*/
private void dumpInfo(MethodInvocation invocation, long ms) {
//擷取被調用方法
Method m = invocation.getMethod();
//擷取被調用方法所屬的對象
Object target = invocation.getThis();
//擷取被調用方法的參數
Object[] args = invocation.getArguments();
System.out.println("所執行的方法: " + m.getName());
System.out.println("對象的類型: " + target.getClass().getName());
System.out.println("方法的參數:");
for (int x = 0; x < args.length; x++) {
System.out.print(" > " + args[x]);
}
System.out.print("\n");
System.out.println("抓取方法運作的時間: " + ms + " ms");
}
}
import org.springframework.aop.framework.ProxyFactory;
/**
* 用戶端測試方法
*/
public class ProfilingExample {
public static void main(String[] args) {
//建立代理對象
WorkerBean bean = getWorkerBean();
//在代理對象上調用業務方法
bean.doSomeWork(10000000);
}
/**
* 代理對象工廠
*/
private static WorkerBean getWorkerBean() {
//建立目标對象
WorkerBean target = new WorkerBean();
//建構代理對象工廠
ProxyFactory factory = new ProxyFactory();
factory.setTarget(target);
factory.addAdvice(new ProfilingInterceptor());
//生産一個代理對象
return (WorkerBean)factory.getProxy();
}
}
運作結果:
- Using JDK 1.4 collections
所執行的方法: doSomeWork
對象的類型: com.apress.prospring.ch6.profiling.WorkerBean
方法的參數:
> 10000000
抓取方法運作的時間: 3453 ms
Process finished with exit code 0
從輸出的結果中,可以看到程式方法調用的方法名、參數、所屬類,以及執行方法所耗費的時間。
另外說一下org.springframework.util.StopWatch類,這是個計時器類,此工具類主要可以擷取計時器類start()和stop()兩次方法調用間的時間。具體可以檢視Spring的API文檔。另外,我也在apache commons 包裡面也有org.apache.common.lang.time.StopWatch。
http://lavasoft.blog.51cto.com/62575/75342/