java - qué - programacion orientada a aspectos en python
Las expresiones de corte de puntos de AspectJ coinciden con las anotaciones de parámetros en cualquier posición (2)
Estoy tratando de definir una expresión de corte de punto para que coincida con los 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 la anotación @Constraint
. Por ejemplo:
Métodos de emparejamiento:
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
¿Alguien puede indicarme la solución correcta? es incluso posible?
Creo que quieres execution(public * *.*(.., @com.example.Constraint *, ..)
, módulo sintaxis.
No puede vincular un argumento en una posición arbitraria a través de args()
en AspectJ porque esto podría llevar a la ambigüedad. Imagínese 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 debería estar vinculado al parámetro args()
nombrado? Entonces mientras
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 que también puede encontrar el primer parámetro o todos los parámetros con la anotación dada, debe hacer exactamente lo que mostré en el otro artículo. Me estoy repitiendo un poco, pero así sea para que la respuesta no se vuelva a eliminar:
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 puede ver, es un poco más complicado obtener las anotaciones de un parámetro dado que solo su tipo declarado, pero básicamente funciona de la misma manera que en mi publicación anterior, es decir, iterando sobre la lista de argumentos.