首页 > 解决方案 > Spring AOP - 自定义注释未在 JoinPoint 中通过

问题描述

我正在尝试使用 Spring AOP 在我的控制器类上捕获一些日志记录数据。

我为此目的使用了自定义注释,但它似乎失败了。

@Around("execution(* path.to.package.endpoints.*Controller.*(..))")
private Object controllerMethodTimer(ProceedingJoinPoint joinPoint) {
    MethodSignature signature = (MethodSignature)joinPoint.getSignature();
    Annotation[][] annotations = signature.getMethod().getParameterAnnotations();
    String[] parameterNames = signature.getParameterNames();
    Object[] parameterValues = joinPoint.getArgs();
    Map<String, String> parameters = new HashMap<>();
    for (Integer i = 0; i < parameterNames.length; i++) {
        for (Annotation annotation : annotations[i]) {
                if (Loggable.class.isInstance(annotation)) {
                    Loggable loggable = (Loggable) annotation;
                if (loggable.name() !=  ""){
                    parameters.put(loggable.name(), parameterValues[i].toString());
                } else {
                    parameters.put(parameterNames[i], parameterValues[i].toString());
                }
            }
        }
    }
//do stuff
//when printing the parameters map, it is always blank
}

可记录类:

public @interface Loggable {

String name() default "";
}

有问题的方法:

public ResponseEntity<Object> defaultLens(RestContext restContext,
                                                @Loggable @RequestBody LensRequest parameters,
                                                @RequestParam(value = "plugins", required = false) String commaDelimitedPluginNames) {
//some stuff
}

我尝试在上面的代码片段中交换 Loggable/RequestBody 的位置。

我发现 Aspect 类循环中的 log.info 将显示 RequestBody 被找到并放置在注释数组中,但 Loggable 不是。

以前使用的代码迭代:

for (Integer i = 0; i < parameterNames.length; i++) {
        Loggable annotation = AnnotationUtils.findAnnotation(parameterValues[i].getClass(), Loggable.class);
        if (annotation != null){
            if (annotation.name() !=  ""){
                parameters.put(annotation.name(), parameterValues[i].toString());
            } else {
                parameters.put(parameterNames[i], parameterValues[i].toString());
            }
        }
    }

发现 Loggable 始终为 null 并且循环的 != null 部分从未被命中。

解析度:

根据下面的评论,自定义注释需要@Retention(RetentionPolicy.RUNTIME)

新的 Loggable 类如下所示:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {

    String name() default "";
}

这是有效的。

标签: javaspringaop

解决方案


推荐阅读