侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

使用Spring AOP实现方法执行日志记录

2025-12-12 / 0 评论 / 4 阅读

题目

使用Spring AOP实现方法执行日志记录

信息

  • 类型:问答
  • 难度:⭐

考点

AOP概念,注解配置,切点表达式

快速回答

使用Spring AOP实现方法日志记录的步骤如下:

  1. 添加Spring AOP依赖(spring-boot-starter-aop)
  2. 创建切面类并用@Aspect@Component注解标记
  3. 使用@Before@Around注解定义通知
  4. 通过切点表达式指定目标方法(如@Pointcut("execution(* com.example.service.*.*(..))")
  5. 在通知方法中实现日志逻辑
## 解析

原理说明

Spring AOP通过动态代理在目标方法执行前后插入横切逻辑(如日志记录)。核心组件:

  • 切面(Aspect):封装横切关注点的模块(如日志切面)
  • 切点(Pointcut):定义哪些方法需要被增强
  • 通知(Advice):增强的具体实现(如@Before)

代码示例

// 1. 添加Maven依赖
// <dependency>
//     <groupId>org.springframework.boot</groupId>
//     <artifactId>spring-boot-starter-aop</artifactId>
// </dependency>

// 2. 定义切面
@Aspect
@Component
public class LoggingAspect {

    // 3. 定义切点(匹配service包下所有方法)
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    // 4. 前置通知
    @Before("serviceMethods()")
    public void logMethodCall(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("执行方法: " + methodName);
    }

    // 5. 环绕通知(带返回值)
    @Around("serviceMethods()")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object result = joinPoint.proceed(); // 执行目标方法
        long duration = System.currentTimeMillis() - start;
        System.out.println(joinPoint.getSignature() + " 执行耗时: " + duration + "ms");
        return result;
    }
}

最佳实践

  • 使用@Around处理耗时统计等需要控制方法执行的场景
  • 优先使用精确的切点表达式(如execution(* com.example.service.UserService.*(..)))避免意外匹配
  • 在通知方法中通过JoinPoint获取方法签名、参数等信息

常见错误

  • 切面未生效:忘记添加@EnableAspectJAutoProxy(Spring Boot中自动配置)
  • 表达式错误:如execution(* *Service(..))漏写通配符导致匹配失败
  • 循环代理:切面方法调用自身导致栈溢出

扩展知识

  • 通知类型
    • @Before:方法执行前
    • @AfterReturning:方法成功返回后
    • @AfterThrowing:方法抛出异常后
    • @After:方法结束后(finally块)
  • 代理机制:Spring AOP默认使用JDK动态代理(需接口),若无接口则用CGLIB
  • 执行顺序:多个切面可通过@Order注解指定优先级