You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot自定义类级别@Loggable注解切面日志失效问题

问题解决:类级别@Loggable注解内部方法调用日志不触发的问题

问题原因

Spring AOP默认基于动态代理实现,只有通过代理对象发起的方法调用才会触发切面逻辑。当类内部方法互相调用时,是通过this引用直接调用目标方法,没有经过代理对象,因此即使类上标注了@Loggable,内部方法的调用也不会被切面拦截,只会在入口方法触发一次日志。

解决方案

方案1:切换为AspectJ织入(推荐,无代码侵入)

AspectJ通过修改字节码实现切面织入,无论方法是内部调用还是外部调用,都能被拦截。

  1. 添加AspectJ依赖(Maven示例):
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.20.1</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.9.20.1</version>
</dependency>
  1. 开启AspectJ织入:

    • 在Spring配置类/启动类上添加注解:
      @EnableAspectJAutoProxy(proxyTargetClass = true)
      
    • Spring Boot项目可在application.properties中配置:
      spring.aop.mode=aspectj
      
  2. 保持原有LoggingAspect和Loggable注解代码不变,此时类内部所有方法调用都会触发日志。

方案2:通过代理对象调用内部方法(代码侵入性强)

在类内部获取当前代理对象,通过代理对象调用内部方法,强制走代理逻辑触发切面。

  1. 开启代理对象暴露:
    在Spring配置类/启动类上添加:
@EnableAspectJAutoProxy(exposeProxy = true)
  1. 修改内部方法调用方式:
@Loggable
@Service
public class YourBusinessService {
    public void entryMethod() {
        // 替换原有this.innerMethod()为代理对象调用
        ((YourBusinessService) AopContext.currentProxy()).innerMethod();
    }

    public void innerMethod() {
        // 业务逻辑
    }
}

关于切入点表达式的说明

你的切入点表达式@within(mypackage.logging.Loggable) || @annotation(mypackage.logging.Loggable)是正确的,它会匹配两类方法:

  • 类上标注@Loggable的所有方法
  • 方法上单独标注@Loggable的方法

内容的提问来源于stack exchange,提问作者TheProgrammer99

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 00:55:35