当前位置: 首页 > 面试题库 >

AspectJ切入点表达式可在任何位置匹配参数注释

松英叡
2023-03-14
问题内容

我试图定义一个切入点表达式以匹配包含用特定注释注释的参数的方法,而不管该参数位于什么位置。在我的情况下,我正在寻找@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

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


问题答案:

您不能通过args()AspectJ
中的任意位置绑定参数,因为这可能导致歧义。试想一下,您有两个或多个相同类型的参数(在这种情况下,使用相同的注释类型进行了注释)。应将其中哪一个绑定到命名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++;
        }
    }
}

如您所见,获取给定参数的注释不仅是声明的类型,还有些棘手,但是基本上它的工作方式与我之前的文章相同,即遍历参数列表。



 类似资料:
  • 到目前为止,我已经尝试了以下表达式,但没有成功: 有人能给我指出正确的解决办法吗?有可能吗?

  • 我试图围绕使用自定义注释注释的方法定义一个切入点。注释有一个参数,我想在切入点定义中包含一个检查。 这是注释: 如何应用注释的示例: 现在我想有两个切入点定义,根据注释的内容选择这两种方法。 在注释本身上创建切入点相对容易: 这将匹配@MyAnno的每次出现。但是我如何定义两个切入点,一个将与包含的匹配,另一个将与包含的匹配

  • 我有一个切入点,我试图用LTW。我有两个方法,我试图建议,每一个与不同的参数列表。但是,它们都有一个我想要的共同参数。 以下是我想建议的方法签名: 我本来希望参数与execution()方法相关联,但有时会出现“混淆”,给我的是IP而不是用户名。 是我不正确地使用了AspectJ,还是这是LTW中的一个bug?我运行的是AspectJ 1.6.13

  • 假设我有一个注释,如下所示: 然后在Aspect中,我怎么可能想写两个切入点,一个用于所有用@DB操作(isRead操作=true)注释的方法,一个用于@DB操作(isRead操作=false)?

  • 问题内容: 如果满足以下条件,则需要创建一个与方法匹配的切入点的方面: 它用MyAnnotationForMethod注释 它的参数之一(可以有多个)用@MyAnnotationForParam注释(但也可以具有其他注释)。 方面类看起来像这样 注释方法 随着日食->警告:在poincut: 使用http://download.eclipse.org/tools/ajdt/35/update中的最