AspectJ切入点表达式匹配任何位置的参数注释

我正在尝试定义切入点表达式以匹配包含用特定注释注释的参数的方法,无论参数位于何处。在我的情况下,我正在寻找@Constraint注释。 例如:

匹配方法:

 public void method1(@Constraint Car car) public void method2(String id, @Constraint Plane plane) public void method3(Wheel wheel, @Constraint List trains, @Constraint Plane plane) public void method4(Motor motor, @Constraint Set 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 strings, @Constraint String s) {} public void method4(int i, @Constraint Set 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 strings = new ArrayList(); strings.add("foo"); strings.add("bar"); Set numbers = new HashSet(); 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++; } } } 

正如您所看到的,获取给定参数的注释比仅使用其声明的类型有点棘手,但基本上它的工作方式与我之前的post相同,即迭代参数列表。

我想你想要execution(public * *.*(.., @com.example.Constraint *, ..) ,模数一些语法。