当前位置: 首页 > 知识库问答 >
问题:

AspectJ:Pointcut声明和检索方法参数的注释

毕瀚
2023-03-14
  • 带注释参数的Spring AOP切入点
  • 如何基于带注释的参数编写方面切入点
  • AspectJ切入点表达式在任意位置匹配参数注释

考虑以下对setter方法的请求

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

我有以下内容,工作很好:

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

如何完成这个目标。有可能吗?我正在使用AspectJ 1.9.6

共有1个答案

淳于思淼
2023-03-14

无论您是否使用..、@myAnnotation(*)、..或仅仅使用@myAnnotation(*),这只消除了可能存在的多个匹配的歧义,都没有直接的方法将方法参数注释绑定到advice参数,只能将方法参数本身绑定到advice参数。这在AspectJ中没有改变。否则,您将在发行说明中看到它,因为它将是一个新特性。

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

有点偏离主题的是,有一个非常古老的Bugzilla票据#233718,它是关于绑定多个匹配(注释)的参数,但不是关于绑定它们的注释。它是在我最近与AspectJ维护者Andy Clement的一次讨论中提出的。但即使有一天这样实施了,也解决不了你的问题。

我想你可以从这里开始,并根据相关问题调整我的解决方案,以满足你的需求。如果你对此有任何后续问题,请随时让我知道,但它应该非常简单。您可能能够进行优化,因为您知道参数的确切位置(考虑数组索引),如果您愿意的话,也就是说,您不需要遍历所有参数。

更新:这里有一个小MCVE给你。它基于这个答案,并被简化为假设注释总是在第一个参数上,并且只在第一个参数上。

请学习什么是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
 类似资料:
  • 问题内容: Java中的方法可以拥有的最大参数数量是什么?为什么? 我在64位Windows系统上使用Java 1.8。 关于StackOverflow的所有答案都表明,技术限制为255个参数,但未指定原因。 确切地说,静态方法为255,非静态方法为254(在这种情况下为第255)。 我认为这可以用某种规范来描述,并且只允许静态定义最大数量的参数。 但这仅对 所有4字节类型有效。我使用参数进行了一

  • Java中的一个方法可以拥有的最大参数数是多少?为什么? 我正在64位Windows系统上使用Java1.8。 准确地说,255用于静态,254用于非静态(在本例中将是第255个)方法。 我认为这可以在某种规范中描述,并且只需要静态定义允许的最大参数数。 但这只对和所有4字节类型有效。我用参数做了一些测试,在那种情况下我只能声明127个参数。 限制与方法的堆栈大小有关系吗? 注意:我真的不打算在任

  • 所以目前,这是我所做的(不起作用): 这是与建议匹配的代码: 以及由junit测试生成的跟踪:

  • 6.1. 方法声明 在函数声明时,在其名字之前放上一个变量,即是一个方法。这个附加的参数会将该函数附加到这种类型上,即相当于为这种类型定义了一个独占的方法。 下面来写我们第一个方法的例子,这个例子在package geometry下: gopl.io/ch6/geometry package geometry import "math" type Point struct{ X, Y floa

  • 我正在尝试编写布尔方法,但它不起作用 它的工作,如果我写这个方法: 我应该如何为它制作布尔方法?

  • 在我的请求中,我有一个参数名“accessToken”,如何从ProceedingJoinPoint获取请求参数值? 调用方法: 我想在AOP中获得这个访问令牌。 提前谢谢。