AspectJ pointcut expression match parameter annotations at any position

后端 未结 2 939
伪装坚强ぢ
伪装坚强ぢ 2020-12-06 05:10

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.

相关标签:
2条回答
  • 2020-12-06 05:33

    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 (*), ..))
    

    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.

    0 讨论(0)
  • 2020-12-06 05:57

    I think you want execution(public * *.*(.., @com.example.Constraint *, ..), modulo some syntax.

    0 讨论(0)
提交回复
热议问题