2012-08-01 6 views
15

Estoy intentando definir una expresión de punto de corte para hacer coincidir métodos que contienen un parámetro anotado con una anotación específica, independientemente de la posición en la que se encuentre el parámetro. En mi caso estoy buscando para la anotación @Constraint. Por ejemplo: métodosAnotaciones de parámetros de concordancia de corte de aspecto AspectJ en cualquier posición

a juego:

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) 

Hasta ahora he intentado las siguientes expresiones sin suerte:

@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 

Puede alguien me punto a la solución correcta? ¿es posible?

+0

Sé que este es viejo, pero sigue sin aparecer como sin respuesta. ¿Podrías aceptar y votar mi respuesta si parece apropiado? Gracias. – kriegaex

Respuesta

12

No se puede vincular un argumento en una posición arbitraria a través de args() en AspectJ porque esto podría generar ambigüedad. Solo imagine que tiene dos o más parámetros del mismo tipo (o anotados por el mismo tipo de anotación en este caso). ¿Cuál de ellos debe estar vinculado al parámetro args() nombrado? Así, mientras que

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

es posible como una expresión independiente (tenga en cuenta los paréntesis alrededor de la estrella), no es posible en combinación con args(). Entonces, si no solo quiere interceptar la ejecución del método en sí, sino también encontrar el primero o todos los parámetros con la anotación dada, debe hacer exactamente lo que mostré en el otro artículo. Estoy un poco repitiendo, pero que así sea para que la respuesta no debe ser eliminada una vez más:

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

Como se puede ver, es un poco más complicado de conseguir las anotaciones de una dado parámetro que solo su tipo declarado, pero básicamente funciona de la misma manera que en mi publicación anterior, es decir, al iterar sobre la lista de argumentos.

1

Creo que quieres execution(public * *.*(.., @com.example.Constraint *, ..), modulo some Sintaxis.

+0

No, esto no funciona para todos los casos que se muestran arriba. – kriegaex

Cuestiones relacionadas