这一主要看看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/