• Spring 面向切面编程 第2关:使用环绕通知统计所有带参方法的执行时间


    目录

    任务描述

    相关知识

    环绕通知

    环绕通知和前后通知的区别

    编程要求

    测试说明

    参考代码


    任务描述

    上一个关卡我们已经学会了怎么使用前后置通知统计出博客系统中博客类中每个业务方法的执行时长。那么环绕通知又是怎么使用的呢?

    本关任务:使用环绕通知统计出目标类中所有带参方法运行时长。

    相关知识

    为了完成本关任务,你需要学习环绕通知。

    环绕通知

    环绕通知是最为强大的通知,它能够让你编写的逻辑将被通知的目标方法完全包裹起来。实际上就像在一个通知方法中同时编写前置通知和后置通知。定义通知的时候在通知方法中添加了入参ProceedingJoinPoint,这个参数是必须写的。因为需要在通知中使用ProceedingJoinPoint.proceed()调用目标方法。

    1. @Around("切点")
    2. public void around(ProceedingJoinPoint point) throws InterruptedException {
    3. //目标方法执行前
    4. System.out.println(" 环绕通知前");
    5. try {
    6. //执行目标方法
    7. point.proceed();
    8. } catch (Throwable throwable) {
    9. throwable.printStackT\frace();
    10. }
    11. //目标方法执行后
    12. System.out.println(" 环绕通知后");
    13. }

    环绕通知和前后通知的区别

    • 目标方法的调用由环绕通知决定,即你可以决定是否调用目标方法,而前置和后置通知是不能决定的,他们只是在方法的调用前后执行通知而已,即目标方法肯定是要执行的;

    • 环绕通知可以控制返回对象,即你可以返回一个与目标对象完全不同的返回值,虽然这很危险,但是你却可以办到。而后置方法是无法办到的,因为他是在目标方法返回值后调用。

    编程要求

    请仔细阅读右侧代码,根据方法内的提示,在切面类(BlogAdvice)中的Begin - End区域内进行代码补充,其中切点已经定义好,不能修改,在此基础上使用环绕通知把目标类(BlogService)中所有有参方法的执行时间统计出来,目标类在右侧代码文件区域可见。

    为了便于评测,我们手动指定程序执行前后的时间,执行前时间2019.1.1 00:00:00,执行后时间2019.1.1 00:01:00。后台IoC容器对象会自动获取目标类实例并调用目标类中所有方法。

    测试说明

    补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。

    预期输出:

    业务功能一

    程序a执行耗时60000


    开始你的任务吧,祝你成功!

    参考代码

    1. package Educoder;
    2. import org.aspectj.lang.ProceedingJoinPoint;
    3. import org.aspectj.lang.annotation.*;
    4. import org.springframework.stereotype.Component;
    5. import java.text.ParseException;
    6. import java.text.SimpleDateFormat;
    7. @Component("BlogAdvice")
    8. @Aspect
    9. public class BlogAdvice {
    10. //定义切点
    11. @Pointcut("execution(* Educoder.BlogService.service*(..))")
    12. public void My() {
    13. }
    14. //定义环绕通知,实现统计目标类所有带参方法运行时长
    15. @Around("My()")
    16. public void around(ProceedingJoinPoint point) throws ParseException, InterruptedException {
    17. /********** Begin **********/
    18. String startStr = "2019.1.1 00:00:00";
    19. String endStr = "2019.1.1 00:01:00";
    20. if(point.getArgs().length>0){
    21. SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
    22. long start = sdf.parse(startStr).getTime();
    23. try {
    24. point.proceed();
    25. } catch (Throwable throwable) {
    26. throwable.printStackTrace();
    27. }
    28. long end = sdf.parse(endStr).getTime();
    29. System.out.println("程序a执行耗时" + (end - start));
    30. }
    31. /********** End **********/
    32. }
    33. }

  • 相关阅读:
    Linear Regression in mojo with NDBuffer
    【Mysql系列】05_JDBC使用
    leetcode 剑指 Offer 33. 二叉搜索树的后序遍历序列
    如何定义需求优先级?
    P1719 最大加权矩形
    Spark学习(7)-SparkSQL函数定义
    【Lychee图床】本地电脑搭建私人图床,公网远程访问
    python 日志处理(基础篇)
    深入理解 Web 协议:HTTP 2
    闭包的产生和问题
  • 原文地址:https://blog.csdn.net/ycq0_9/article/details/127677380