Spring AOP 本質(4)
這一主要看看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。