【问题标题】:@AspectJ pointcut for methods that override an interface method with an annotation使用注解覆盖接口方法的方法的@AspectJ 切入点
【发布时间】:2023-03-03 11:11:01
【问题描述】:

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

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

切入点execution(@MyAnnotation * *.*(..)) 仅在B.method() 本身带有注释时才匹配。还有其他方法吗?

【问题讨论】:

  • 我在使用 JAX-RS Annotation javax.ws.rs.Path 时遇到了类似的问题。我项目中的所有资源路径都在接口中定义,我想切入它。到现在为止我都失败得很惨。

标签: java aop aspectj pointcuts pointcut


【解决方案1】:

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

有关方法/库的更多信息可以找到here.

【讨论】:

    【解决方案2】:

    更新

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

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

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

    原始答案

    来自Spring 3.0 Documentation

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

    我在7.8.2 Other Spring aspects for AspectJ 部分发现了这一点,它是7.8 Using AspectJ with Spring applications 的一部分,这让我觉得这是一个全局规则。

    【讨论】:

    • 谢谢;这就解释了为什么我的切入点不起作用。但是,我正在寻找一种有效的方法。 :-)
    • @hstoerr:在你编辑了你的问题之后,我编辑了我的答案。如果仍然无法接受,请告诉我。
    • 春季文档实际上并没有说不可能匹配我想要的东西 - 只是我尝试的简单方法不起作用。在 Aspectj 中可能会有一些我想不到的奇怪事情。所以我还是很期待的。 :-)
    • 可以接受方法名称吗?这将需要传播给实现者,并且可以通过 AspectJ 实现。
    【解决方案3】:
    //introducing empty marker interface
    declare parents : hasmethod(@MyAnnotation * *(..)) implements TrackedParentMarker;
    
    public pointcut p1() : execution(* TrackedParentMarker+.*(..));
    

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

    【讨论】:

    • 不幸的是,它并没有做到这一点。它适用于实现接口的所有类的每个方法,该接口具有至少一个带有注释的方法。但它应该仅适用于使用该标记实现接口方法的一种方法。或者至少对于与标记接口方法具有相同名称的方法,如果在 AspectJ 中可以这么说的话。
    • @alehro 您如何配置应用程序以使用 *.aj 文件?你能看看这个问题stackoverflow.com/questions/50391609/…吗?
    猜你喜欢
    • 2019-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2018-05-08
    • 2014-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多