2012-08-01 12 views
15

Sto provando a definire un'espressione pointcut per abbinare metodi che contengono un parametro annotato con un'annotazione specifica, indipendentemente dalla posizione in cui si trova il parametro. Nel mio caso sto cercando per l'annotazione @Constraint. Per esempio: i metodiAspectJ pointcut expression abbina annotazioni parametro in qualsiasi posizione

coordinati:

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) 

Finora ho provato le seguenti espressioni senza fortuna:

@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 

Qualcuno mi può indicare la soluzione giusta? è anche possibile?

+0

So che questo è vecchio, ma ancora elencato come senza risposta. Vorresti accettare e revocare la mia risposta se mi sembra opportuno? Grazie. – kriegaex

risposta

12

Non è possibile associare un argomento in una posizione arbitraria tramite args() in AspectJ perché ciò potrebbe causare ambiguità. Immagina di avere due o più parametri dello stesso tipo (o annotati dallo stesso tipo di annotazione in questo caso). Quale di questi deve essere associato al parametro args() denominato? Così, mentre

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

è possibile come espressione autonoma (si prega di notare le parentesi intorno alla stella), non è possibile in combinazione con args(). Quindi, se non vuoi solo intercettare l'esecuzione del metodo stesso, ma anche trovare il primo o tutti i parametri con l'annotazione specificata, devi fare esattamente quello che ho mostrato nell'altro articolo. Sto un pò mi ripeto, ma così sia in ordine per la risposta non da cancellare di nuovo:

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

Come si può vedere, si tratta di un po 'più complicato per ottenere le annotazioni di un dato parametro oltre al suo tipo dichiarato, ma fondamentalmente funziona allo stesso modo del mio post precedente, vale a dire iterando sull'elenco di argomenti.

1

Penso che tu voglia execution(public * *.*(.., @com.example.Constraint *, ..), modulo qualche sintassi.

+0

No, questo non funziona per tutti i casi mostrati sopra. – kriegaex

Problemi correlati