Spring Boot自定义类级别@Loggable注解切面日志失效问题
问题解决:类级别@Loggable注解内部方法调用日志不触发的问题
问题原因
Spring AOP默认基于动态代理实现,只有通过代理对象发起的方法调用才会触发切面逻辑。当类内部方法互相调用时,是通过this引用直接调用目标方法,没有经过代理对象,因此即使类上标注了@Loggable,内部方法的调用也不会被切面拦截,只会在入口方法触发一次日志。
解决方案
方案1:切换为AspectJ织入(推荐,无代码侵入)
AspectJ通过修改字节码实现切面织入,无论方法是内部调用还是外部调用,都能被拦截。
- 添加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>
开启AspectJ织入:
- 在Spring配置类/启动类上添加注解:
@EnableAspectJAutoProxy(proxyTargetClass = true) - Spring Boot项目可在
application.properties中配置:spring.aop.mode=aspectj
- 在Spring配置类/启动类上添加注解:
保持原有
LoggingAspect和Loggable注解代码不变,此时类内部所有方法调用都会触发日志。
方案2:通过代理对象调用内部方法(代码侵入性强)
在类内部获取当前代理对象,通过代理对象调用内部方法,强制走代理逻辑触发切面。
- 开启代理对象暴露:
在Spring配置类/启动类上添加:
@EnableAspectJAutoProxy(exposeProxy = true)
- 修改内部方法调用方式:
@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
相关产品推荐
相关产品推荐

