使用Spring AOP来统计方法的执行时间

一、解决方案

1、传统方法

最简单、粗暴的方法是给各个需要统计的方法开始和结尾处加的时间戳,然后差值计算结果即可,代码如下:


[html]  view plain  copy
  1. long startTime = System.currentTimeMillis();  
  2.   
  3. // 业务代码  
  4.   
  5. long endTime = System.currentTimeMillis();    
  6. System.out.println("程序运行时间:" + (endTime - startTime) + "ms");    //输出程序运行时间    

这样的方式需要给很多统计方法都加上耗时时间的代码,这些代码与核心业务无关却大量重复、分散在各处,维护起来也困难。

2、面向切面编程的方法

所以,不推荐使用上面的代码。利用 spring AOP的思想来完成这个功能,代码和相关的解释如下:

[html]  view plain  copy
  1. import org.apache.commons.logging.Log;    
  2. import org.apache.commons.logging.LogFactory;    
  3. import org.aspectj.lang.ProceedingJoinPoint;    
  4. import org.aspectj.lang.annotation.Around;    
  5. import org.aspectj.lang.annotation.Aspect;    
  6. import org.aspectj.lang.reflect.MethodSignature;    
  7. import org.springframework.stereotype.Component;  
  8.   
  9. /**  
  10.  * 检测方法执行耗时的spring切面类  
  11.  * 使用@Aspect注解的类,Spring将会把它当作一个特殊的Bean(一个切面),也就是不对这个类本身进行动态代理  
  12.  * @author blinkfox  
  13.  * @date 2016-07-04  
  14.  */  
  15. @Aspect  
  16. @Component  
  17. public class TimeInterceptor {  
  18.   
  19.     private static Log logger = LogFactory.getLog(TimeInterceptor.class);  
  20.   
  21.     // 一分钟,即60000ms  
  22.     private static final long ONE_MINUTE = 60000;  
  23.   
  24.     // service层的统计耗时切面,类型必须为final String类型的,注解里要使用的变量只能是静态常量类型的  
  25.     public static final String POINT = "execution (* com.blinkfox.test.service.impl.*.*(..))";  
  26.   
  27.     /**  
  28.      * 统计方法执行耗时Around环绕通知  
  29.      * @param joinPoint  
  30.      * @return  
  31.      */  
  32.     @Around(POINT)  
  33.     public Object timeAround(ProceedingJoinPoint joinPoint) {  
  34.         // 定义返回对象、得到方法需要的参数  
  35.         Object obj = null;  
  36.         Object[] args = joinPoint.getArgs();  
  37.         long startTime = System.currentTimeMillis();  
  38.   
  39.         try {  
  40.             obj = joinPoint.proceed(args);  
  41.         } catch (Throwable e) {  
  42.             logger.error("统计某方法执行耗时环绕通知出错", e);  
  43.         }  
  44.   
  45.         // 获取执行的方法名  
  46.         long endTime = System.currentTimeMillis();  
  47.         MethodSignature signature = (MethodSignature) joinPoint.getSignature();  
  48.         String methodName = signature.getDeclaringTypeName() + "." + signature.getName();  
  49.   
  50.         // 打印耗时的信息  
  51.         this.printExecTime(methodName, startTime, endTime);  
  52.   
  53.         return obj;  
  54.     }  
  55.   
  56.     /**  
  57.      * 打印方法执行耗时的信息,如果超过了一定的时间,才打印  
  58.      * @param methodName  
  59.      * @param startTime  
  60.      * @param endTime  
  61.      */  
  62.     private void printExecTime(String methodName, long startTime, long endTime) {  
  63.         long diffTime = endTime - startTime;  
  64.         if (diffTime > ONE_MINUTE) {  
  65.             logger.warn("-----" + methodName + " 方法执行耗时:" + diffTime + " ms");  
  66.         }  
  67.     }  
  68.   
  69. }  

注意:最后还需要在  applicationContext.xml 文件中加上AOP需要的配置  <aop:aspectj-autoproxy/> ,这样Spring才能识别到它。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP(Aspect-Oriented Programming)是Spring框架中的一个模块,用于实现面向切面编程。Spring AOP可以在运行时动态地将代码织入到目标对象的方法中,从而实现一些横切关注点的功能,如日志记录、性能统计、事务管理等。 以下是Spring AOP使用步骤: 1.在Spring配置文件中启用AOP。 ```xml <beans xmlns:aop="http://www.springframework.org/schema/aop"> <aop:aspectj-autoproxy/> </beans> ``` 2.定义切面类,即实现横切功能的类。 ```java @Aspect public class LoggingAspect { @Before("execution(* com.example.demo.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Method " + joinPoint.getSignature().getName() + " is called."); } } ``` 3.在切面类中定义通知,即横切功能的具体实现。 ```java @Before("execution(* com.example.demo.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Method " + joinPoint.getSignature().getName() + " is called."); } ``` 4.在目标对象中使用切面。 ```java @Service public class UserService { public void addUser(User user) { //... } } ``` 5.在目标对象中使用切面。 ```xml <bean id="userService" class="com.example.demo.service.UserService"/> <bean id="loggingAspect" class="com.example.demo.aspect.LoggingAspect"/> <aop:config> <aop:aspect ref="loggingAspect"> <aop:before pointcut="execution(* com.example.demo.service.*.*(..))" method="logBefore"/> </aop:aspect> </aop:config> ``` 以上就是Spring AOP的基本使用方法。需要注意的是,Spring AOP只支持基于代理的AOP实现,因此需要在目标对象上使用接口。另外,Spring AOP只能拦截方法调用,无法拦截属性访问等其他操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值