原创

AOP切面实现打印日志出入参

温馨提示:
本文最后更新于 2023年02月12日,已超过 439 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

在项目中,经常需要定位问题,在分析问题的过程中最需要的是方法的出入参。
但是如果每个方法都需要开发人员自己打印出入参,那就非常的麻烦了。
今天就通过,切面的方式在不改变业务逻辑的情况下,打印方法的出入参

项目地址:
https://gitee.com/it1997/it1997-demo.git

依赖引入

SpringBoot中使用aop需要引入依赖

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.7.3</version>
</dependency>

新增Controller

TestController

package com.it1997.controller;

import com.it1997.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")
public class TestController {
    @Autowired
    UserService userService;

    @PostMapping("/qryUser")
    public String qryUserInfo(@RequestBody String user) {
        return userService.qryUserInfo(user);
    }
}

定义切面

通过切面实现打印每个接口的出入参
@Aspect 注解声明该类为一个切面
@Component 将该类交给spring容器管理

LogAspect.java

package com.it1997.Aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class LogAspect {

    /**
     * 这个切面的切入点
     * controller 包下的全部方法
     */
    @Pointcut("execution(* com.it1997.controller.TestController.*(..))")
    public void pointcut() {
        // 切面切入点
    }

    /**
     * 环绕通知,围绕切入点所作的操作
     */
    @Around("pointcut()")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = joinPoint.proceed();// 执行方法
        long endTime = System.currentTimeMillis();
        Signature signature = joinPoint.getSignature();
        String className = String.valueOf(joinPoint.getTarget().getClass());
        String methodName = signature.getName();
        Object[] args = joinPoint.getArgs();

        System.out.println("====入参====");
        for (Object arg : args) {
            System.out.println(arg.toString());
        }

        System.out.println("====出参====");
        System.out.println(result.toString());
        System.out.println("调用"+className+"."+methodName+"==>"+"耗时"+(endTime - startTime)+"ms");

    }
}

切面内容详解

定义切点,即那个地方执行切面里的方法
@Pointcut("execution( com.it1997.controller.TestController.(..))")

@Before: 前置通知 在切入点执行前执行切面方法
@AfterRetunring: 后置通知 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
@Around: 环绕通知 可以自定义在方法执行前和执行后执行那些内容
@AfterThrowing: 异常通知 用来处理当切入内容部分抛出异常之后的处理逻辑
@After: 最终通知 在切入点结尾处切入内容

最终效果

file

正文到此结束
本文目录