Spring-AOP计算方法运行所需时间

AOP计算方法运行所需时间

一,前言

  利用SpringAOP切面完成对java方法的运行时间计算

二,准备

  创建JavaWeb项目,配置Spring,创建方法类,测试类,切面类

三,代码实现

 1.配置xml文件 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

<!-- 定义目标对象 -->

<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:切入点  同时配置后置/异常/最终通知时:按照配置的先后顺序执行 --><br><br>    <!-- 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类

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

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) {<br>        System.out.println("arg:"+o);<br>      }

      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.测试类

1

2

3

4

5

6

7

8

9

10

11

12

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);<br>    Object object = stuimpl.test(12);<br>    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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过在方法前后添加时间戳,然后计算时间差来计算方法耗时。也可以使用Spring AOP的拦截器,在方法执行前后记录时间戳,然后计算时间差。以下是一个使用Spring AOP计算方法耗时的示例: 1. 定义一个切面类,实现MethodInterceptor接口 ```java @Component @Aspect public class TimingAspect implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { long startTime = System.currentTimeMillis(); Object result = invocation.proceed(); long endTime = System.currentTimeMillis(); long elapsedTime = endTime - startTime; System.out.println(invocation.getMethod().getName() + " 方法耗时:" + elapsedTime + "ms"); return result; } } ``` 2. 在配置文件中启用AOP,并将切面类作为切点 ```xml <aop:aspectj-autoproxy /> <bean id="timingAspect" class="com.example.TimingAspect" /> <aop:config> <aop:aspect ref="timingAspect"> <aop:pointcut expression="execution(* com.example.service.*.*(..))" /> <aop:around method="invoke" /> </aop:aspect> </aop:config> ``` 3. 在需要计算耗时的方法上加上@LogExecutionTime注解 ```java @Service public class MyService { @LogExecutionTime public void doSomething() { // do something } } ``` 4. 定义@LogExecutionTime注解和切面类 ```java @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface LogExecutionTime { } @Component @Aspect public class TimingAspect { @Around("@annotation(com.example.LogExecutionTime)") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long startTime = System.currentTimeMillis(); Object result = joinPoint.proceed(); long endTime = System.currentTimeMillis(); long elapsedTime = endTime - startTime; System.out.println(joinPoint.getSignature().getName() + " 方法耗时:" + elapsedTime + "ms"); return result; } } ``` 这样,在调用doSomething方法时,就会输出方法耗时的信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值