且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-09-26 12:20:44

   由于项目主管提出统计每个方法执行的具体时间,打印到日志以后方便分析问题。这个也是很常用的办法,但是我们调用的外部模块非常多,每个地方都加上一个时间统计就显得非常难看了。所以这个事情当然还是交给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,如需转载请自行联系原作者