简体   繁体   English

@AspectJ切入点覆盖带有注释的接口方法的方法

[英]@AspectJ pointcut for methods that override an interface method with an annotation

How can I write an aspectj pointcut that applies to method executions which override an interface method with an annotation? 如何编写适用于覆盖带注释的接口方法的方法执行的aspectj切入点? For example: 例如:

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

The pointcut execution(@MyAnnotation * *.*(..)) does only match if B.method() carries the annotation itself. 切入点execution(@MyAnnotation * *.*(..))仅在B.method()带有注释本身时才匹配。 Is there another way to do this? 还有另一种方法吗?

As Nicholas pointed out, this is not possible in AspectJ. 正如尼古拉斯指出的那样,这在AspectJ中是不可能的。 Here is more proof of why it is not possible (taken from http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html section Annotation Inheritance and pointcut matching): 这里有更多证据证明为什么它不可能(取自http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations-pointcuts-and-advice.html部分注释继承和切入点匹配):

According to the Java 5 specification, non-type annotations are not inherited, and annotations on types are only inherited if they have the @Inherited meta-annotation. 根据Java 5规范,非类型注释不会被继承,类型注释只有在具有@Inherited元注释的情况下才会被继承。 The call to c2.aMethod (that would be b.method() in your example) is not matched because join point matching for modifiers (the visibility modifiers, annotations, and throws clause) is based on the subject of the join point (the method actually being called). 对c2.aMethod的调用(在您的示例中将是b.method())不匹配,因为修饰符的连接点匹配(可见性修饰符,注释和throws子句)基于连接点的主题(实际被调用的方法)。

Having suffered from this same issue, I have written a small method/library that would allow you to write pointcuts for such methods. 遇到同样的问题,我写了一个小方法/库,可以让你为这些方法编写切入点。 Here is how it would work for your example: 以下是它如何适用于您的示例:

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

OR 要么

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

The method implementsAnnotation(String,JoinPoint) is coming from the library; 方法implementsAnnotation(String,JoinPoint)来自库; a basic method that checks if the implemented methods contain the specified annotation. 检查实现的方法是否包含指定注释的基本方法。

More information about the method/library can be found here. 有关方法/库的更多信息,请参见此处。

Update 更新

Since it appears that it cannot be done in Spring (see original answer) I would say that you need to add the annotation to each method on the implementing classes. 由于它似乎无法在Spring中完成(请参阅原始答案),我想说您需要在实现类的每个方法上添加注释。 There is an obvious way to do this, but I suppose if you are looking for a more automatic way you will need to write one yourself. 有一种明显的方法可以做到这一点,但我想如果你正在寻找一种更自动的方式,你需要自己写一个。

I can imagine some sort of home-grown post-processor that will look for a specific annotation, lets say @ApplyThisAnnotationToAllWhoInheritMe . 我可以想象某种本土的后处理器,它会寻找一个特定的注释,比如@ApplyThisAnnotationToAllWhoInheritMe Once it finds this annotation, it would scan sourcecode for inheriting members and add the requested annotation where necessary before compilation happens. 一旦找到此注释,它将扫描源代码以继承成员,并在编译发生之前在必要时添加所请求的注释。

Regardless, if you are using Spring AOP to do this, it appears that it needs to be on the implementers method. 无论如何,如果您使用Spring AOP执行此操作,它似乎需要在实现方法上。 If the classes you are hoping this will help are out of your control, you may have to write your own Spring AOP tool. 如果您希望这将有助于您的课程不受您的控制,您可能必须编写自己的Spring AOP工具。

Original Answer 原始答案

From the Spring 3.0 Documentation : Spring 3.0文档

AspectJ follows Java's rule that annotations on interfaces are not inherited. AspectJ遵循Java的规则,即接口上的注释不会被继承。

I found this bit in section 7.8.2 Other Spring aspects for AspectJ , which is a part of 7.8 Using AspectJ with Spring applications , which makes me think this is a global rule. 我在第7.8.2 Other Spring aspects for AspectJ节中介绍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+.*(..));

Also you should enable –XhasMember compiler flag. 您还应该启用-XhasMember编译器标志。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM