java @AspectJ 切入点,用于使用注释覆盖接口方法的方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7178782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 18:58:20  来源:igfitidea点击:

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

javaaopaspectjpointcutspointcut

提问by Hans-Peter St?rr

How can I write an aspectj pointcut that applies to method executions which override an interface method with an annotation? 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. Is there another way to do this?

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

采纳答案by Guven

As Nicholas pointed out, this is not possible in 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.htmlsection Annotation Inheritance and pointcut matching):

正如 Nicholas 指出的那样,这在 AspectJ 中是不可能的。这是为什么不可能的更多证据(取自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. 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).

根据 Java 5 规范,非类型注解不会被继承,类型注解只有在具有 @Inherited 元注解时才会被继承。对 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; a basic method that checks if the implemented methods contain the specified annotation.

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

More information about the method/library can be found here.

可以在此处找到有关该方法/库的更多信息

回答by nicholas.hauschild

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. 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.

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

I can imagine some sort of home-grown post-processor that will look for a specific annotation, lets say @ApplyThisAnnotationToAllWhoInheritMe. Once it finds this annotation, it would scan sourcecode for inheriting members and add the requested annotation where necessary before compilation happens.

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

Regardless, if you are using Spring AOP to do this, it appears that it needs to be on the implementers method. 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 来执行此操作,则它似乎需要在实现者方法上。如果您希望这会有所帮助的类超出了您的控制,您可能需要编写自己的 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.

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

回答by alehro

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

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

Also you should enable –XhasMember compiler flag.

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