利用AOP实现对方法执行时间的统计

通过Spring AOP实现方法执行时间的记录及日志输出,避免在业务代码中添加时间统计逻辑,简化代码并提高维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   由于项目主管提出统计每个方法执行的具体时间,打印到日志以后方便分析问题。这个也是很常用的办法,但是我们调用的外部模块非常多,每个地方都加上一个时间统计就显得非常难看了。所以这个事情当然还是交给spring的AOP功能代理掉,就算那天不想统计时间了,清除这个功能也异常容易。下面给出一个小例子,非常的简单。

    首先,给出一个Mouse的对象,他有几个基本的动作,我们就统计这些动作的具体执行时间。

 

  1. package log; 
  2.  
  3. public class Mouse { 
  4.      
  5.     public String click(){ 
  6.         System.out.println("click"); 
  7.         return "clicked me"
  8.     } 
  9.      
  10.     public void move(){ 
  11.         System.out.println("move"); 
  12.         try { 
  13.             Thread.sleep(1000); 
  14.         } catch (InterruptedException e) { 
  15.             e.printStackTrace(); 
  16.         } 
  17.     } 
  18.  

 

    然后编写一个对于时间统计的类作为aspect。

  1. package log; 
  2.  
  3. import org.apache.log4j.Logger; 
  4. import org.aspectj.lang.ProceedingJoinPoint; 
  5.  
  6. public class LogAspect { 
  7.  
  8.     private Logger logger = Logger.getLogger(LogAspect.class); 
  9.      
  10.     public Object invoke(ProceedingJoinPoint joinPoint) throws Throwable {  
  11.         logger.warn("Beginning method: " + joinPoint.toLongString());  
  12.         long startTime = System.currentTimeMillis();  
  13.         Object result; 
  14.         try{  
  15.             result = joinPoint.proceed();  
  16.         }finally{  
  17. logger.warn("Method invocation time: " + (System.currentTimeMillis() - startTime) + " ms.");             
  18.         }  
  19.         return result; 
  20.    } 
  21.      

    最关键的就是在配置文件声明横切面和具体执行类,注意这个bean必须在spring容器里面才行。

  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <beans xmlns="http://www.springframework.org/schema/beans"    
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  4.     xmlns:aop="http://www.springframework.org/schema/aop"    
  5.     xsi:schemaLocation="     
  6. http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
  7. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
  8.      
  9.     <bean id="logAspect" class="log.LogAspect"/> 
  10.      
  11.     <bean id="mouse" class="log.Mouse"/> 
  12.    
  13.     <aop:config>    
  14.         <aop:pointcut id="logPointCut" expression="execution( * log.Mouse.*(..))" />    
  15.         <aop:aspect ref="logAspect">    
  16.             <aop:around pointcut-ref="logPointCut" method="invoke" />    
  17.         </aop:aspect>    
  18.     </aop:config>    
  19.  
  20. </beans> 

 

    最后给出执行的测试类

  1. package log; 
  2.  
  3. import org.springframework.context.ApplicationContext; 
  4. import org.springframework.context.support.ClassPathXmlApplicationContext; 
  5.  
  6. public class LogTest { 
  7.      
  8.     public static ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app*.xml"); 
  9.      
  10.     public static void main(String[] args) { 
  11.         Mouse m = (Mouse) applicationContext.getBean("mouse"); 
  12.         System.out.println(m.click()); 
  13.         m.move(); 
  14.     } 
  15.  

 

    这里再提下asm,这个横切进入的实现就是依靠asm的动态生成中间字节码,在生成字节码的动作中把具体的实现混入进去了。不得不赞叹一下~!



本文转自passover 51CTO博客,原文链接:http://blog.51cto.com/passover/479386,如需转载请自行联系原作者

### Java AOP 实现记录方法执行时间 为了实现通过AOP记录Java应用程序中的方法执行时间,可以采用`@AspectJ`风格的配置方式,在Spring框架下定义切面逻辑。下面是一个具体的例子说明如何利用`@Around`通知完成这一功能。 #### 定义日志切面类 创建一个名为LoggingAspect的日志切面类并标注为组件以便于自动扫描发现它: ```java import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Component @Aspect public class LoggingAspect { @Around("execution(* com.example.service..*(..))") // 切入点表达式匹配特定包下的所有方法 public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); try { return joinPoint.proceed(); // 继续执行目标方法 } finally { long executionTime = System.currentTimeMillis() - start; System.out.printf("%s executed in %d ms%n", joinPoint.getSignature(), executionTime); } } } ``` 这段代码展示了如何使用`@Around`注解包裹住实际的目标方法调用,并在其前后添加额外的行为——这里是在方法开始前获取当前时间戳,在结束后再次读取并与前者相减得到总耗时[^1]。 #### 配置文件设置 确保项目中有适当的应用上下文配置以支持AOP特性。如果使用的是基于XML的方式,则需在`applicationContext.xml`中加入如下片段启用全局代理模式以及指定要加载哪些Bean作为方面: ```xml <aop:aspectj-autoproxy /> <context:component-scan base-package="com.example"/> ``` 对于现代版本的Spring应用来说,更推荐完全依赖注解驱动的方式来简化配置过程;此时只需确认已开启组件扫描即可[^2]。 #### 测试验证效果 编写简单的单元测试或者控制台程序去触发受监控的服务接口操作,观察输出结果是否包含了预期的时间统计信息。例如上述提到的例子中,当调用了`us.a()`或`us.b(int)`这样的服务层函数之后,应该能在终端看到形如“methodX executed in Y ms”的提示语句[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值