【问题标题】:AspectJ: Pointcut to declare and retrieve an annotation of a method's parameterAspectJ:声明和检索方法参数注释的切入点
【发布时间】:2020-09-17 07:11:22
【问题描述】:

我已阅读以下有价值的链接:

考虑这个对setter方法的请求

public void setSomething(@ParameterLevel(name="abc") String something){
   this.something = something;
}

我有以下并且工作正常:

@Pointcut("execution(* *.*(@somepackage.ParameterLevel (*)))")
void parameterLevel01() {}

现在我想通过如下方法的参数检索@ParameterLevel 注释:

@Pointcut("execution(* *.*(@somepackage.ParameterLevel (*)))")
void parameterLevel01(ParameterLevel parameterLevel) {} <--To be used directly in the advice method

目的是直接使用Annotation如何在advice方法中作为参数

类似的东西,例如:

@within(classLevel)@ClassLevel 在:

@ClassLevel
public class SomeClass {
  ...
}

@annotation(methodLevel)@MethodLevel 输入:

   @MethodLevel
   public void somethingToDo(){
     ...
   }

如何实现这一目标。有可能吗?我正在使用 AspectJ 1.9.6

【问题讨论】:

  • 我不明白你为什么在这里问这个问题。您阅读了其他已重复的问题,我想您也阅读了我接受的两个答案。您是否真的认为,如果可以像您希望的那样将参数注释绑定到建议方法参数的简单方法是可能的,我会发布更复杂的方法吗?
  • 此外,在签名中使用.., something, .. 意味着something 可以出现多次,因此将其绑定到单个值参数将是不明确的。您可以想象将其绑定到一个数组,但在今天(AspectJ 1.9.6)这是不可能的。所以请使用我的解决方案。谢谢。
  • .., something, .. 已更新为被删除。现在即将只有一个参数。此外,在我的帖子末尾说 How accomplish this goal. Is possible? 我可以假设对于 AspectJ 的新版本添加了支持或功能。
  • You read the other questions of which this is a duplicate already and I guess you also read my two accepted answers 我的问题不是重复的,因为帖子中没有请求直接在通知方法中检索参数的注释,它只是将切入点应用于方法带有注释的参数。不一样
  • 就像我说的,答案就在您已经找到的其他问题中。我在这里的回答有点多余,只是已经存在的一种变体。这只是对你的礼貌。你很幸运,我不得不在机场消磨时间,等待转机。 ??????

标签: java annotations aop aspectj


【解决方案1】:

无论您使用.., @MyAnnotation (*), .. 还是仅使用@MyAnnotation (*),这只会消除可能存在多个匹配项的歧义,没有直接的方法可以将方法参数注释绑定到通知参数,只有方法参数本身。这在 AspectJ 中没有改变。否则,您会在发行说明中看到它,因为这将是一项新功能。

因此,您将不得不使用您在问题中已链接到的其他两个答案中的方法,即手动迭代参数类型和注释。

有点题外话,有一个非常古老的Bugzilla ticket #233718 是关于绑定多个匹配(注释)的参数,而不是关于绑定它们的注释。它出现在我与 AspectJ 维护者 Andy Clement 最近的discussion 中。但即使有一天实现了,也解决不了你的问题。

我认为您可以从这里获取它,并根据您的需求调整我的解决方案,从链接的问题中获取。如果您对此有任何后续问题,请随时告诉我,但这应该非常简单。如果您愿意,您可能能够优化,因为您知道确切的参数位置(想想数组索引),即您不需要遍历所有参数。


更新:这是给你的小MCVE。它基于this answer,并已简化为假设注释始终位于第一个参数且仅位于第一个参数上。

请了解 MCVE 是什么,并在下次自己提供一份,因为这是你的工作,而不是我的工作。这是您的免费拍摄。

标记注解+驱动应用:

package de.scrum_master.app;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;

@Retention(RUNTIME)
public @interface ParameterLevel {
  String name();
}
package de.scrum_master.app;

public class Application {
  public static void main(String[] args) {
    new Application().doSomething("foo");
  }

  public void doSomething(@ParameterLevel(name="abc") String string) {}
}

方面:

package de.scrum_master.aspect;

import java.lang.annotation.Annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.SoftException;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;

import de.scrum_master.app.ParameterLevel;

@Aspect
public class ParameterLevelAspect {
  @Before("execution(public * *(@de.scrum_master.app.ParameterLevel (*))) && args(string)")
  public void beforeAdvice(JoinPoint thisJoinPoint, String string) {
    System.out.println(thisJoinPoint + " -> " + string);
    MethodSignature signature = (MethodSignature) thisJoinPoint.getSignature();
    String methodName = signature.getMethod().getName();
    Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
    Annotation[] annotations;
    try {
      annotations = thisJoinPoint.getTarget().getClass()
        .getMethod(methodName, parameterTypes)
        .getParameterAnnotations()[0];
    } catch (NoSuchMethodException | SecurityException e) {
      throw new SoftException(e);
    }
    ParameterLevel parameterLevel = null;
    for (Annotation annotation : annotations) {
      if (annotation.annotationType() == ParameterLevel.class) {
        parameterLevel = (ParameterLevel) annotation;
        break;
      }
    }
    assert parameterLevel != null;
    System.out.println("  " + parameterLevel + " -> " + parameterLevel.name());
  }
}

控制台日志:

execution(void de.scrum_master.app.Application.doSomething(String)) -> foo
  @de.scrum_master.app.ParameterLevel(name="abc") -> abc

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    • 2013-02-12
    相关资源
    最近更新 更多