AOP计算方法运行所需时间

一,前言

二,准备

  创建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

猜你喜欢

转载自www.cnblogs.com/liujie783/p/11940135.html