AOP計算方法運行所需時間


一,前言

  利用SpringAOP切面完成對java方法的運行時間計算

二,准備

  創建JavaWeb項目,配置Spring,創建方法類,測試類,切面類

三,代碼實現

 1.配置xml文件 

<!-- 定義目標對象 -->
<bean id="stuimpl" class="com.stu.impl.StuImpl"></bean>
<!-- 定義切面對象 -->
<bean id="log" class="com.stu.Log"></bean>
		
<!-- 切面配置 -->
<aop:config>
  <!-- 切入點表達式:execution:具體到方法,within:具體到類,類中的所有方法,*:任意字符 ..:多層
	execution(public void com.aaa.aop3.BookImpl.add(int))
	execution(* * com..*.select*(..)) 
	within(com.aaa.aop3.BookImpl):com.aaa.aop3.BookImpl下的所有方法
	within(com.aaa.aop3.*):com.aaa.aop3包下所有類中所有方法
  -->
		
  <!-- 定義一個可以被多個切面共享的切入點 -->
  <!-- <aop:pointcut expression="within(com.aaa.aop3.BookImpl)" id="points"/> -->
  <aop:pointcut expression="execution(* com.stu.impl.StuImpl.*(..))" id="points"/>
	
  <!-- 將id=log的對象作為切面使用 -->
  <aop:aspect ref="log">
    <!-- method:方法  pointcut-ref:切入點  同時配置后置/異常/最終通知時:按照配置的先后順序執行 -->

    <!-- before:前置通知,總是在連接點調用前執行 -->     <!-- <aop:before method="start" pointcut-ref="points"/> -->     <!-- 后置通知:在方法正常執行完成之后調用 -->     <!-- <aop:after-returning method="afterReturning" pointcut-ref="points"/> -->     <!-- 異常通知:在方法異常執行之后調用 -->     <!-- <aop:after-throwing method="afterThrowing" pointcut-ref="points" throwing="e"/> -->     <!-- 最終通知:在方法執行完成之后調用 -->     <!-- <aop:after method="after" pointcut-ref="points"/> -->     <!-- 環繞通知:圍繞方法的執行前后執行 -->     <aop:around method="around" pointcut="execution(* com.stu.impl.StuImpl.*(..))"/>   </aop:aspect> </aop:config>

  2.Log類

 

package com.stu;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;

public class Log {
  //定義方法開始時間和結束時間
  long startTime;
  long afterTime;
  
  public void start() {
    //獲取系統當前時間的毫秒數
    startTime = System.currentTimeMillis();
    System.out.println("前置通知before");
  }

  // JoinPoint:連接點對象
  public void after(JoinPoint jp) {
    System.out.println("最終通知after");
    afterTime = System.currentTimeMillis();
    Signature signature = jp.getSignature();
    System.out.println(signature.getDeclaringTypeName()+"."+signature.getName()+"方法執行了"+(afterTime-startTime)+"ms");	
  }

  public void afterReturning() {
    System.out.println("后置通知afterReturning");
  }

  public void afterThrowing(JoinPoint jp,Exception e) throws Exception {
    System.out.println("異常通知afterThrowing");
    System.out.println("發生異常,異常的原因是" + e.getMessage());
  }

  /**
  * ProceedingJoinPoint:正在執行的連接點,只能寫在環繞通知中
   * 
   * @return返回值表示的連接點的返回值
   */
  public Object around(ProceedingJoinPoint pjp) {
    Object obj = null;
    System.out.println("環繞通知around");
    try {
      System.out.println("環繞前置通知");
      startTime = System.currentTimeMillis();
      // proceed():執行連接點,返回連接點的返回值

      // 獲取正在執行的連接點對象所在的類,打印結果:class org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint
      Class<? extends ProceedingJoinPoint> class1 = pjp.getClass();
      //System.out.println("class:" + class1);

      // 當前執行的連接點,打印結果:int com.stu.impl.StuImpl.update(int,int)
      Signature signature = pjp.getSignature();
      //System.out.println("signature:" + signature);

      // 連接點的方法名,打印結果:update
      String name = signature.getName();
      //System.out.println("name:" + name);
			
      // 連接點所在的類,打印結果:class com.stu.impl.StuImpl
      Class declaringType = signature.getDeclaringType();
      //System.out.println("declaringType:" + declaringType);
			
      // 連接點所在的類名全路徑,打印結果:com.stu.impl.StuImpl
      String declaringTypeName = signature.getDeclaringTypeName();
      //System.out.println("declaringTypeName:" + declaringTypeName);

      // 調用連接點的目標對象,打印結果:com.stu.impl.StuImpl@6e4784bc
      Object target = pjp.getTarget();
      //System.out.println("target:" + target);

      // 連接點傳遞的參數列表
      Object[] args = pjp.getArgs();
      System.out.println("args.length:" + args.length);
      for (Object o : args) {
        System.out.println("arg:"+o);
      }       obj = pjp.proceed();       System.out.println("環繞后置通知");     } catch (Throwable e) {       System.out.println("環繞異常通知");       Signature signature = pjp.getSignature();       System.out.println(signature.getDeclaringTypeName()+"."+signature.getName()+"方法時發生異常,異常的原因是" + e.getMessage());     } finally {       System.out.println("環繞最終通知");       afterTime = System.currentTimeMillis();       Signature signature = pjp.getSignature();       System.out.println(signature.getDeclaringTypeName()+"."+signature.getName()+"方法執行了"+(afterTime-startTime)+"ms");     }     return obj;   } }

  3.測試類

package com.stu;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.stu.impl.StuImpl;

public class StuTest {
  public static void main(String[] args) {
		
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");	
    StuImpl stuimpl = context.getBean(StuImpl.class);
    Object object = stuimpl.test(1, 2);
    System.out.println("object的值"+o);   } }

  4.打印結果:使用環繞通知,異常后返回值0,使用Object接受返回值並輸出

    環繞通知around
    環繞前置通知
    args.length:2
    arg:1
    arg:2
    test方法
    環繞后置通知
    環繞最終通知
    com.stu.impl.StuImpl.test方法執行了16ms
    object的值1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM