【问题标题】:AspectJ pointcut expression match parameter annotations at any positionAspectJ 切入点表达式匹配任意位置的参数注释
【发布时间】:2012-07-30 17:56:27
【问题描述】:

我正在尝试定义一个切入点表达式以匹配包含使用特定注释注释的参数的方法,而不管参数在什么位置。在我的情况下,我正在寻找 @Constraint 注释。例如:

匹配方法:

public void method1(@Constraint Car car)

public void method2(String id, @Constraint Plane plane)

public void method3(Wheel wheel, @Constraint List<Train> trains, @Constraint Plane plane)

public void method4(Motor motor, @Constraint Set<Train> trains, Bicycle bike, Wheel wheel)

public void method5(Wing wing, Motorcycle moto, @Constraint Truck truck, Bicycle bike, Wheel wheel)

到目前为止,我尝试了以下表达式,但没有成功:

@Before("execution(public * *.*(..)) and @args(com.example.Constraint)") // there can be only one parameter
@Before("execution(public * *.*(..)) and @args(..,com.example.Constraint)") // parameter must be in last position
@Before("execution(public * *.*(..)) and @args(com.example.Constraint,..)") // parameter must be in first position
@Before("execution(public * *.*(..)) and (@args(com.example.Constraint,..) or @args(..,com.example.Constraint))") // parameter must be in first or last position, nothing in between
@Before("execution(public * *.*(..)) and @args(..,com.example.Constraint,..)") // Invalid

有人能指出正确的解决方案吗?有可能吗?

【问题讨论】:

    标签: java spring aop aspectj spring-aop


    【解决方案1】:

    我想你想要execution(public * *.*(.., @com.example.Constraint *, ..),以一些语法为模。

    【讨论】:

      【解决方案2】:

      您不能在 AspectJ 中通过 args() 在任意位置绑定参数,因为这可能会导致歧义。想象一下,您有两个或多个相同类型的参数(或在这种情况下由相同的注释类型注释)。其中哪一个应该绑定到命名的args() 参数?所以虽然

      execution(public * *(.., @Deprecated (*), ..))
      

      可以作为独立表达式(请注意星号周围的括号),不能与args() 结合使用。因此,如果您不仅想拦截方法执行本身,还想找到带有给定注释的第一个或所有参数,您需要按照我在另一篇文章中展示的内容进行操作。我有点重复自己,但为了避免再次删除答案:

      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      
      @Retention(RetentionPolicy.RUNTIME)
      public @interface Constraint {}
      
      import java.util.ArrayList;
      import java.util.HashSet;
      import java.util.List;
      import java.util.Set;
      
      public class Application {
          public void method1(@Constraint int i) {}
          public void method2(String id, @Constraint float f) {}
          public void method3(int i, @Constraint List<String> strings, @Constraint String s) {}
          public void method4(int i, @Constraint Set<Integer> numbers, float f, boolean b) {}
          public void method5(boolean b, String s, @Constraint String s2, float f, int i) {}
          public void notIntercepted(boolean b, String s, String s2, float f, int i) {}
      
          public static void main(String[] args) {
              List<String> strings = new ArrayList<String>();
              strings.add("foo");
              strings.add("bar");
              Set<Integer> numbers = new HashSet<Integer>();
              numbers.add(11);
              numbers.add(22);
              numbers.add(33);
      
              Application app = new Application();
              app.method1(1);
              app.method2("foo", 1f);
              app.method3(1, strings, "foo");
              app.method4(1, numbers, 1f, true);
              app.method5(false, "foo", "bar", 1f, 1);
              app.notIntercepted(false, "foo", "bar", 1f, 1);
          }
      }
      
      import java.lang.annotation.Annotation;
      
      import org.aspectj.lang.SoftException;
      import org.aspectj.lang.reflect.MethodSignature;
      
      public aspect ArgCatcherAspect {
          before() : execution(public * *(.., @Constraint (*), ..)) {
              System.out.println(thisJoinPointStaticPart);
              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();
              } catch (Exception e) {
                  throw new SoftException(e);
              }
              int i = 0;
              for (Object arg : thisJoinPoint.getArgs()) {
                  for (Annotation annotation : annotations[i]) {
                      if (annotation.annotationType() == Constraint.class)
                          System.out.println("  " + annotation + " -> " + arg);
                  }
                  i++;
              }
          }
      }
      

      如您所见,获取给定参数的注释比仅获取其声明的类型有点棘手,但基本上它的工作方式与我之前的帖子中的相同,即通过迭代参数列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-25
        • 2018-05-08
        • 2011-02-15
        相关资源
        最近更新 更多