AspectJ 切入点表达式匹配任意位置的参数注释 [英] AspectJ pointcut expression match parameter annotations at any position

查看:34
本文介绍了AspectJ 切入点表达式匹配任意位置的参数注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to define a pointcut expression to match methods which contain a parameter annotated with a specific annotation, regardless of what position the parameter is in. In my case I'm looking for the @Constraint annotation. For example:

匹配方法:

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)

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

So far I've tried the following expressions with no luck:

@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

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

Can someone point me to the right solution? is it even possible?

推荐答案

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

You cannot bind an argument at an arbitrary position via args() in AspectJ because this could lead to ambiguity. Just imagine you have two or more parameters of the same type (or annotated by the same annotation type in this case). Which one of them should be bound to the named args() parameter? So while

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

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

is possible as a stand-alone expression (please note the parentheses around the star), it is not possible in combination with args(). So if you do not just want to intercept the method execution itself, but also find the first or all parameters with the given annotation you need to do just what I showed in the other article. I am kinda repeating myself, but so be it in order for the answer not to be deleted again:

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++;
        }
    }
}

如您所见,获取给定参数的注释比仅获取其声明的类型要复杂一些,但基本上它的工作方式与我之前的帖子相同,即通过迭代参数列表.

As you can see, it is a bit trickier to get the annotations of a given parameter than just its declared type, but basically it works the same way as in my previous post, i.e. by iterating over the list of arguments.

这篇关于AspectJ 切入点表达式匹配任意位置的参数注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆