2012-08-01 17 views
15

Ich versuche einen Pointcut Ausdruck zu definieren, um Methoden zu finden, die einen mit einer bestimmten Anmerkung versehenen Kommentar enthalten, unabhängig davon, in welcher Position der Parameter ist. In meinem Fall suche ich für die @Constraint Annotation. Zum Beispiel:AspectJ pointcut Ausdruck Übereinstimmung Parameter Anmerkungen an jeder Position

Matching-Methoden:

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) 

Bisher habe ich die folgenden Ausdrücke ohne Glück versucht:

@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 

Kann mir jemand auf die richtige Lösung zeigen? ist es überhaupt möglich?

+0

Ich weiß, das ist alt, aber immer noch als unbeantwortet aufgeführt. Würden Sie bitte meine Antwort akzeptieren und auffrischen, wenn es angemessen erscheint? Vielen Dank. – kriegaex

Antwort

12

Sie können kein Argument an einer beliebigen Position über args() in AspectJ binden, da dies zu Mehrdeutigkeiten führen kann. Stellen Sie sich vor, Sie haben zwei oder mehr Parameter desselben Typs (oder in diesem Fall mit dem gleichen Anmerkungstyp). Welcher von ihnen sollte an den genannten args() Parameter gebunden sein? So, während

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

ist möglich, als Stand-alone-Ausdruck (bitte die Klammern um den Stern beachten), ist es nicht möglich, in Kombination mit args(). Wenn Sie also nicht nur die Ausführung der Methode abfangen, sondern auch den ersten oder alle Parameter mit der gegebenen Anmerkung finden möchten, müssen Sie genau das tun, was ich in dem anderen Artikel gezeigt habe. Ich wiederhole irgendwie selbst, aber so ist es für die Antwort sein, um nicht wieder gelöscht werden:

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

Wie Sie sehen können, ist es ein bisschen schwieriger ist es, die Anmerkungen von a zu erhalten gegebener Parameter als nur sein deklarierter Typ, aber im Grunde funktioniert es genauso wie in meinem vorherigen Post, dh durch Iterieren über die Liste von Argumenten.

1

Ich denke, Sie wollen execution(public * *.*(.., @com.example.Constraint *, ..), modulo einige Syntax.

+0

Nein, das funktioniert nicht in allen oben gezeigten Fällen. – kriegaex