java - 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 "";
}
这是有效的。
解决方案
推荐阅读
- sql - 在oracle中对没有排序的列进行排名
- javascript - 根据变量的类型调用不同的函数时,正确的流类型模式是什么?
- json - Angular HttpClient 返回字符串数据而不是解析的 JSON
- excel - VBA检查对象是否在自由区域内部或外部
- docker - Jenkins 的工作卡在作为代理执行 docker 映像
- c# - 用来自组合框的数据填充文本框,与 xml 连接
- r - 如何在不从 y 轴移除刻度的情况下抑制水平网格线?
- google-analytics - 如何分析奇怪的目标流结果?是否可以查看特定用户的旅程?
- asp.net-core - 将多个 Razor 页面呈现为 Html
- reactjs - 当我单击面板上的按钮时,有没有办法防止 React 中的侧面板重新渲染(滚动回面板顶部)?