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

Spring Boot自定义注解+AOP实现方法审计及问题排查

Spring Boot自定义注解AOP审计功能实现问题排查与修复

需求背景

正在开发Spring Boot应用,希望通过自定义注解实现方法审计功能,最初设计的注解为@AuditMetod,标注示例如下:

@AuditMetod(name = "SomeValue")
foo() {...}

期望的最简审计逻辑为:

auditMethod(Method method) {
    if (method.hasAnnotation(AuditMethod.class)) {
        System.out.println (method.getName() + " was called at " + new Date())
    }
}

现存问题

确认使用Spring AOP实现该需求后,遇到两个问题:

  • 切面类逻辑未触发,日志未输出预期的----------ASPECT METHOD IS CALLED-----------内容
  • 不知道如何在切面方法中获取当前拦截的目标方法对应的Method类实例

当前已编写的代码如下:

Controller层代码

@PostMapping
@LoggingRest(executor = "USER", method = "CREATE", model = "SUBSCRIPTION")
public ResponseEntity<?> create(@Valid @RequestBody SubscriptionRequestDto dto) {
   ...
}

自定义注解代码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoggingRest {
    String executor() default "SYSTEM";
    String method() default "";
    String model() default "";
}

切面类代码

@Aspect
@Slf4j
@Component
public class AuditAspect {
    @Pointcut(value = "@annotation(com.aspect.annotations.LoggingRest)")
    public void auditMethod(ProceedingJoinPoint proceedingJoinPoint) {
        log.info("----------ASPECT METHOD IS CALLED------------");
    }
}

问题修复方案

切面未触发问题修复

切面不生效的核心原因是AOP注解用法错误,同时需要确认依赖配置正确:

  1. 先引入Spring AOP依赖,Spring Boot项目直接引入官方starter即可:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 修正切点用法:@Pointcut标注的方法仅作为切点定义标记,不能写业务逻辑,该方法返回值必须为void,不需要定义参数。
  2. 补充实际的增强通知(@Around/@Before/@After等)绑定切点,编写审计逻辑。
    注意:请确认@Pointcut中配置的注解全类名和你实际定义LoggingRest注解的包路径完全一致,否则切点无法匹配到目标方法

获取目标Method实例方法

在通知方法中通过JoinPoint获取方法签名,强转为MethodSignature后即可拿到对应的Method对象,同时可以直接读取注解上的配置参数。

修复后的完整切面代码

@Aspect
@Slf4j
@Component
public class AuditAspect {

    // 正确定义切点:无参数、无业务逻辑,仅作为标记
    @Pointcut(value = "@annotation(com.aspect.annotations.LoggingRest)")
    public void auditPointCut() {}

    // 使用环绕通知绑定切点,编写实际审计逻辑
    @Around("auditPointCut()")
    public Object aroundAudit(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("----------ASPECT METHOD IS CALLED------------");
        // 获取目标方法的Method实例
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method targetMethod = signature.getMethod();
        
        // 获取方法上的注解实例,读取配置参数
        LoggingRest auditAnnotation = targetMethod.getAnnotation(LoggingRest.class);
        String executor = auditAnnotation.executor();
        String operateMethod = auditAnnotation.method();
        String model = auditAnnotation.model();

        // 执行原方法逻辑
        Object result = joinPoint.proceed();

        // 自定义审计逻辑示例
        log.info("方法{}被调用,操作人:{},操作类型:{},操作模块:{},调用时间:{}",
                targetMethod.getName(),
                executor,
                operateMethod,
                model,
                new Date());

        return result;
    }
}

如果不需要控制原方法执行时机,仅需要在方法执行前打印审计日志,可以把@Around替换为@Before,参数使用JoinPoint即可,不需要调用proceed()方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 08:36:26