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

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

问题描述

我正在尝试定义切入点表达式以匹配包含使用特定注释注释的参数的方法,而不管参数位于何处。在我的情况下,我正在寻找 @约束注释。例如:

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?

推荐答案

你不能通过 args()<绑定任意位置的参数AspectJ中的/ code>因为这可能导致歧义。想象一下,您有两个或更多相同类型的参数(在这种情况下由相同的注释类型注释)。应该将哪一个绑定到命名的 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天全站免登陆