Выражение pointcut AspectJ соответствует аннотациям параметров в любой позиции

Я пытаюсь определить выражение pointcut для сопоставления методов, которые содержат параметр, аннотированный определенной аннотацией, независимо от того, в какой позиции находится параметр. В моем случае я ищу аннотацию @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

Может ли кто-нибудь указать мне правильное решение? это вообще возможно?


person driangle    schedule 01.08.2012    source источник


Ответы (2)


Вы не можете привязать аргумент в произвольной позиции через 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++;
        }
    }
}

Как видите, получить аннотации данного параметра немного сложнее, чем просто его объявленный тип, но в основном это работает так же, как и в моем предыдущем посте, т. е. путем перебора списка аргументов.

person kriegaex    schedule 24.03.2013

Я думаю, вы хотите execution(public * *.*(.., @com.example.Constraint *, ..) по модулю некоторого синтаксиса.

person Judge Mental    schedule 01.08.2012