20

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

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

切入点仅在带有注释本身execution(@MyAnnotation * *.*(..))时才匹配。B.method()还有另一种方法可以做到这一点吗?

4

3 回答 3

12

正如 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)来自图书馆;检查实现的方法是否包含指定注释的基本方法。

有关方法/库的更多信息可以在这里找到。

于 2011-09-19T03:23:05.217 回答
4

更新

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

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

无论如何,如果您使用 Spring AOP 来执行此操作,它似乎需要在 implementationers 方法上。如果您希望这会有所帮助的类超出您的控制范围,您可能必须编写自己的 Spring AOP 工具。

原始答案

来自Spring 3.0 文档

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

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

于 2011-08-24T16:26:18.570 回答
2
//introducing empty marker interface
declare parents : hasmethod(@MyAnnotation * *(..)) implements TrackedParentMarker;

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

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

于 2011-08-25T09:29:31.460 回答