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



如何编写适用于用注释覆盖接口方法的方法执行的aspectj切入点?例如:

interface A {
  @MyAnnotation void method();
}
class B implements A {
  void method();
}

切入点execution(@MyAnnotation * *.*(..))只有在B.method()携带注释本身的情况下才匹配。有别的办法吗?

正如Nicholas所指出的,这在AspectJ中是不可能的。以下是为什么它不可能的更多证据(摘自http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html部分注释继承和切入点匹配(:

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

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

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

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

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

有关该方法/库的更多信息,请访问此处。

更新

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

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

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

原始答案

来自Spring 3.0文档:

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

我在7.8.2 Other Spring aspects for AspectJ部分找到了这个比特,它是7.8 Using AspectJ with Spring applications的一部分,这让我认为这是一个全局规则。

//introducing empty marker interface
declare parents : hasmethod(@MyAnnotation * *(..)) implements TrackedParentMarker;
public pointcut p1() : execution(* TrackedParentMarker+.*(..));

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

最新更新