我正在尝试定义一个切入点表达式,以匹配包含用特定注释注释的参数的方法,而不管参数在什么位置。在我的情况下,我正在寻找@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
有人能给我指出正确的解决方案吗?这可能吗?
不能通过AspectJ中的args()
在任意位置绑定参数,因为这可能会导致歧义。假设您有两个或多个相同类型的参数(或者在本例中由相同的注释类型进行注释)。其中哪一个应该绑定到命名的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++;
}
}
}
正如您所看到的,获取给定参数的注释比获取其声明的类型要困难一些,但基本上它的工作方式与我上一篇文章中的相同,即迭代参数列表。
我想你想要execution(public * *.*(.., @com.example.Constraint *, ..)
,模化一些语法。