Java @使用注释重写接口方法的方法的AspectJ切入点

Java @使用注释重写接口方法的方法的AspectJ切入点,java,aop,aspectj,pointcuts,pointcut,Java,Aop,Aspectj,Pointcuts,Pointcut,如何编写一个aspectj切入点,应用于用注释重写接口方法的方法执行?例如: interface A { @MyAnnotation void method(); } class B implements A { void method(); } 切入点执行(@MyAnnotation**.*(..)仅在B.method()携带注释本身时匹配。还有其他方法吗?更新 因为它似乎不能在Spring中完成(参见原始答案),所以我认为您需要将注释添加到实现类的每个方法中。有一个明显的方法可以做

如何编写一个aspectj切入点,应用于用注释重写接口方法的方法执行?例如:

interface A {
  @MyAnnotation void method();
}
class B implements A {
  void method();
}
切入点
执行(@MyAnnotation**.*(..)
仅在
B.method()
携带注释本身时匹配。还有其他方法吗?

更新

因为它似乎不能在Spring中完成(参见原始答案),所以我认为您需要将注释添加到实现类的每个方法中。有一个明显的方法可以做到这一点,但我想如果你正在寻找一个更自动的方法,你需要自己写一个

我可以想象某种自制的后处理器会寻找特定的注释,比如说
@ApplyThisAnnotationToAllWhoInheritMe
。一旦找到此注释,它将扫描源代码以查找继承的成员,并在编译之前在必要的位置添加请求的注释

无论如何,如果您使用SpringAOP来实现这一点,那么它似乎需要位于implementers方法上。如果您希望它能够帮助的类超出了您的控制范围,那么您可能必须编写自己的SpringAOP工具

原始答案

从:

AspectJ遵循Java的规则,即不继承接口上的注释

我在AspectJ的
7.8.2其他Spring特性
一节中找到了这一点,这是
7.8在Spring应用程序中使用AspectJ的一部分,这使我认为这是一条全局规则

//introducing empty marker interface
declare parents : hasmethod(@MyAnnotation * *(..)) implements TrackedParentMarker;

public pointcut p1() : execution(* TrackedParentMarker+.*(..));

您还应该启用–XhasMember编译器标志。

正如Nicholas指出的,这在AspectJ中是不可能的。下面是不可能的原因的更多证明(取自节注释继承和切入点匹配):

根据Java5规范,非类型注释不会被继承,而类型上的注释只有在具有@inherited元注释时才会被继承。对c2.aMethod的调用(在您的示例中是b.method())不匹配,因为修饰符(可见性修饰符、注释和抛出子句)的连接点匹配基于连接点的主题(实际调用的方法)

在经历了同样的问题之后,我编写了一个小方法/库,允许您为这些方法编写切入点。下面是您的示例的工作方式:

myAnnotationIsExecuted(): execution(public * *.*(..)) && 
             if(implementsAnnotation("@MyAnnotation()", thisJoinPoint));

方法
implementsAnnotation(String,JoinPoint)
来自库;检查实现的方法是否包含指定注释的基本方法


有关方法/库的更多信息,请参见

谢谢;这就解释了为什么我的切入点不起作用。但是,我正在寻找一个有效的。:-)@你编辑了你的问题后,我编辑了我的答案。让我知道这是否仍然是不可接受的。spring文档实际上并没有说不可能匹配我想要的东西——只是我尝试的简单方法不起作用。在Aspectj中可能有一些奇怪的事情我想不起来。所以我还是希望……-)以方法的名称命名是否可以接受?这将需要传播到实现者,并且可以通过AspectJ实现。不幸的是,这并不能完全实现。它适用于实现接口的所有类中的每个方法,该接口至少有一个带有注释的方法。但它应该只应用于使用该标记实现接口方法的一个方法。或者至少是与标记的接口方法同名的方法,如果可以在AspectJ中这样说的话。@alehro您是如何配置应用程序使用*.aj文件的?您能看一下这个问题吗?我在JAX-RS注释javax.ws.RS.Path中面临着类似的问题。我的项目中所有资源的路径都是在接口中定义的,我想切入它。到现在为止,我一直失败得很惨。
myAnnotationIsExecuted(): execution(public * A+.*(..)) &&
             if(implementsAnnotation("@MyAnnotation()", thisJoinPoint));