利用Spring AOP记录方法的执行时间

yizhihongxing

利用Spring AOP记录方法的执行时间可以通过以下步骤实现:

1. 添加依赖

pom.xml文件中添加Spring AOP的依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>${spring.version}</version>
</dependency>

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>${aspectj.version}</version>
</dependency>

2. 定义切面类

切面类必须实现org.aspectj.lang.annotation.Aspect接口,并使用@Aspect注解标记:

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class PerformanceAspect {
    private static final Logger logger = LoggerFactory.getLogger(PerformanceAspect.class);

    @Pointcut("execution(* com.example.demo.controller.*.*(..))")
    public void controllerExecution() {}

    @Before("controllerExecution()")
    public void beforeControllerExecution() {
        logger.info("Start executing controller");
    }

    @After("controllerExecution()")
    public void afterControllerExecution() {
        logger.info("Finish executing controller");
    }
}

上述代码定义了一个切面类PerformanceAspect,用来记录所有Controller中方法的执行时间。其中,@Pointcut注解用于定义切入点,该切入点匹配所有Controller中的方法;@Before@After注解用于在目标方法执行之前和执行之后分别执行自定义的逻辑。

3. 配置AOP

在Spring配置文件中添加如下配置:

<aop:aspectj-autoproxy />
<bean id="performanceAspect" class="com.example.demo.aop.PerformanceAspect" />

上述配置会自动扫描并代理Spring容器中的所有@Aspect注解标记的切面类。

4. 测试

定义一个简单的Controller:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {

    @GetMapping("/hello")
    public String hello() throws InterruptedException {
        Thread.sleep(1000);
        return "Hello, World!";
    }
}

启动应用程序并访问http://localhost:8080/hello,控制台将输出如下日志:

Start executing controller
Finish executing controller

日志表明,PerformanceAspect切面类成功地拦截了DemoController中的方法,并记录了方法的执行时间。下面再提供一条完整的代码示例:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class SystemLogAspect {

    private static final Logger log = LoggerFactory.getLogger(SystemLogAspect.class);

    /**
     * 定义切入点,拦截所有带有RequestMapping注解的方法
     */
    @Pointcut("execution(public * com.scienjoy.app.web..*Controller.*(..)) && @annotation(org.springframework.web.bind.annotation.RequestMapping)")
    public void controllerMethod() {
    }

    /**
     * 前置通知,方法调用前被调用
     * @param joinPoint 连接点对象,封装了被拦截方法的信息
     */
    @Before("controllerMethod()")
    public void beforeMethod(JoinPoint joinPoint) {
        log.info("调用了 " + joinPoint.getTarget().getClass().getName() + " 的 " + joinPoint.getSignature().getName() + " 方法,参数: " + joinPoint.getArgs());
    }

    /**
     * 后置通知,在方法执行完毕后执行,无论方法成功执行还是出现异常都会执行
     * @param joinPoint 连接点对象
     * @param result 方法返回值
     */
    @AfterReturning(pointcut = "controllerMethod()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        //把返回值转化为String类型,防止调用toString()方法时出现空指针异常
        String ret = result != null ? result.toString() :"null";
        log.info("调用 " + joinPoint.getTarget().getClass().getName() + " 的 " + joinPoint.getSignature().getName() + " 方法成功结束,返回值: " + ret);
    }

    /**
     * 异常通知,在拦截的方法出现异常时被调用
     * @param joinPoint 连接点对象
     * @param throwable 异常对象
     */
    @AfterThrowing(pointcut = "controllerMethod()", throwing = "throwable")
    public void afterThrowing(JoinPoint joinPoint, Throwable throwable) {
        log.error("调用 " + joinPoint.getTarget().getClass().getName() + " 的 " + joinPoint.getSignature().getName() + " 方法时出现异常: " + throwable.getMessage());
    }

    /**
     * 环绕通知,可以控制拦截方法的执行过程
     * @param proceedingJoinPoint 连接点
     * @return 拦截方法执行结果
     * @throws Throwable 异常
     */
    @Around("controllerMethod()")
    public Object aroundMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        log.info("开始调用 " + proceedingJoinPoint.getTarget().getClass().getName() + " 的 " + proceedingJoinPoint.getSignature().getName() + " 方法");
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            throw throwable;
        } finally {
            long endTime = System.currentTimeMillis();
            log.info("调用 " + proceedingJoinPoint.getTarget().getClass().getName() + " 的 " + proceedingJoinPoint.getSignature().getName() + " 方法结束,耗时: " + (endTime - startTime) + "ms");
        }
        return result;
    }
}

该切面类实现了前置通知、后置通知、异常通知以及环绕通知功能,能够较全面地记录方法执行时间和出现的异常情况。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:利用Spring AOP记录方法的执行时间 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • Eclipse中配置Maven的图文教程

    下面是Eclipse中配置Maven的详细攻略: 步骤一:下载安装Maven 首先,我们需要下载并安装Maven,这里我们推荐使用Apache Maven官方网站提供的二进制版本。以下是下载Maven的步骤: 访问官方网站:https://maven.apache.org/download.cgi 选择最新的二进制版本进行下载。 下载完成后,解压到本地某个目…

    Java 2023年5月19日
    00
  • MyBatis使用Zookeeper保存数据库的配置可动态刷新的实现代码

    下面我将为你详细讲解使用Zookeeper保存数据库的配置并实现动态刷新的实现过程。本文主要分为以下几个部分: MyBatis使用Zookeeper保存数据库的配置的原理 实现动态刷新的流程 代码实现及示例说明 1. MyBatis使用Zookeeper保存数据库的配置的原理 MyBatis使用Zookeeper保存数据库的配置,可以将配置信息保存在Zook…

    Java 2023年6月16日
    00
  • Spring Boot 自定义数据源DruidDataSource代码

    那么关于Spring Boot自定义数据源DruidDataSource的完整攻略,主要分为以下几个步骤: 导入相关依赖 首先,在Spring Boot项目中,需要导入Druid和JDBC相关的依赖。可以在pom.xml文件中加入如下代码: <!– 导入Druid数据源依赖 –> <dependency> <groupId&…

    Java 2023年5月20日
    00
  • java中String的一些方法深入解析

    Java中String的一些方法深入解析 String类简介 在Java程序中,String是一个重要的类,它用来表示字符串。String类是Java中一个不可变类,也就是说,一旦字符串创建,就不能改变其内容。在使用String时经常需要用到一些其方法来操作字符串。 常用String方法 charAt方法 charAt方法用来获取字符串中指定索引位置的字符,…

    Java 2023年5月27日
    00
  • mybatis对于list更新sql语句的写法说明

    当我们需要对列表数据进行更新时,MyBatis提供了一些方便的写法。下面将对mybatis对于list更新sql语句的写法进行详细讲解: update语句的基本写法 MyBatis对于update语句的写法与一般的SQL语句一致,使用update关键字指定更新表,使用set关键字指定列的新值,使用where关键字指定更新的条件。 update user se…

    Java 2023年5月20日
    00
  • spring security自定义决策管理器

    下面来详细讲解一下“spring security自定义决策管理器”的完整攻略。 什么是决策管理器 Spring Security是一个基于Spring的安全框架,其中涉及到许多安全相关的处理,包括鉴权(Authentication)和授权(Authorization)等。使用Spring Security,我们可以通过配置来管理系统中不同的权限,而决策管理…

    Java 2023年5月20日
    00
  • centos7安装Tomcat7的教程图解

    CentOS7安装Tomcat7的教程图解 第一步:安装JDK 首先,要安装JDK,可以使用CentOS默认仓库中的OpenJDK或者Oracle官网下载。 示例1:使用CentOS默认仓库中的OpenJDK安装 sudo yum install java-1.8.0-openjdk-devel 示例2:从Oracle官网下载JDK安装 # 下载二进制文件 …

    Java 2023年5月19日
    00
  • 详解Tomcat双击startup.bat闪退的解决方法

    下面是“详解Tomcat双击startup.bat闪退的解决方法”的完整攻略。 问题背景 当我们在Windows系统上双击Tomcat的startup.bat启动脚本时,有时会出现闪退的情况。这可能是由于某些配置或系统环境问题导致的。下面我们将详解解决这一问题的方法。 解决方法 方法一:修改startup.bat文件 步骤如下: 打开Tomcat的安装目录,…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部