【问题标题】:Custom annotation not getting argument's value自定义注释没有得到参数的值
【发布时间】:2019-11-12 17:21:49
【问题描述】:

在 Spring 中编写它并尝试使用自定义注释,该注释从方法的参数中获取值并对其执行一些逻辑。 但它不起作用。它最终打印出我传入的字符串值,而不是变量的值。

示例变量名为name,其值为“Dan”。当我传入参数时,它最终会打印出“name”而不是“Dan”。 如果我在 Spring 中对 Cacheable 注释做同样的事情,它工作得很好。使用 Intellij 甚至基于 ide 的突出显示,当我将参数传递给 @Cacheable 时,它​​似乎可以识别该参数,但对于我的自定义注释却不是这样。请指教我做错了什么。

我的自定义注释

@Target(ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnot {
    String key();
}

实现注释。当我期待“Dan”时,这会错误地打印出“#key”

@CustomAnnot(key = "#key")
public Object getObj(String key) {
    return null;
}

为可缓存的有效的传递相同表达式的示例。

@Cacheable(key = "#key")
public Object getAnotherObj(String key) {
    return null;
}

相信这段代码不会引起任何问题。只是添加它以防万一。使用注释重定向到发生打印的 Aspect 类,我在其中验证它是否打印错误。

@Around("@annotation(CustomAnnot)")
public Object get(ProceedingJoinPoint pjp, CustomAnnot customAnnot) throws Throwable {
    String key = customAnnot.key();
    System.out.println(key);
}

【问题讨论】:

  • 请发帖minimal reproducible exampleperformMocking.key() 是什么?你的意思是customAnnot.key()?当您分配给注释元素 key 时,您为什么期望它返回除 "#key" 以外的任何内容?
  • @SotiriosDelimanolis 是的,已修改。通过传入#key,我期望它在方法的参数中获取字符串键值。不是这样吗?它发生在 Cacheable 上。
  • 注解并不神奇。 Cacheable 背后有一个完整的库来处理带注释的方法/类。现在,您实际上只是在检索您在此处指定的内容 @CustomAnnot(key = "#key")
  • @SotiriosDelimanolis 这里有什么建议。我确实需要一种方法让我的自定义注释获取我的参数值。需要它来自这里的注释。由于其他设计到位,不能采用任何反射方法。猜想尝试图书馆来解决这个问题将是矫枉过正。我没想到注释会起作用,但希望 Spel(表达式语言)能够获取参数值。猜不出来..
  • 不太了解你的情况,但如果你想要的只是参数值,你知道你可以从pjp.getArgs() 得到它,如果你想比较参数名称,你可以从(MethodSignature) pjp.getStaticPart().getSignature().getParameterNames()

标签: java annotations spring-aop


【解决方案1】:

如果你想要的只是基于你的 key 的参数值,你可以做这样的事情。忽略了异常处理。

@Around("@annotation(customAnnot)")
  public Object get(ProceedingJoinPoint pjp, CustomAnnot customAnnot) throws Throwable {
    MethodSignature signature = (MethodSignature) pjp.getStaticPart().getSignature();
    List<String> paramsList = Arrays.asList(signature.getParameterNames());
    List<Object> argsList = Arrays.asList(pjp.getArgs());
    String key = customAnnot.key();
    key = key.substring(1);

    logger.info("[{}]", argsList.get(paramsList.indexOf(key)));
    return key;
  }

打电话

test.getObj("Dan");

打印: [丹]

【讨论】:

  • 是的,但我需要灵活处理不同数量的参数、类型和顺序。示例方法A(字符串a,字符串b),也许我只想捕获字符串b。另一种方法B(String a, String b, String c) 在这里只需要String c,或者在另一种情况下我需要2个参数。
【解决方案2】:

仅使用注释无法实现您所要求的。注释在编译期间被处理并嵌入到类字节码中,此时它们的存在和它们的属性值是固定的。注释属性值的任何处理都必须由基本 java 注释 API 之上的层来完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 2020-02-14
    • 1970-01-01
    • 1970-01-01
    • 2021-11-23
    • 2021-12-06
    • 1970-01-01
    相关资源
    最近更新 更多