【问题标题】:Spring AOP point cut for 'nested' annotation“嵌套”注释的 Spring AOP 切入点
【发布时间】:2015-07-15 20:12:45
【问题描述】:

我需要定义一个切入点,该切入点触发对使用自定义注释进行注释的 spring 服务的所有方法的执行。我想定义切点的注释将在另一个注释上。

@Y
public @interface X {
}

然后服务将被注释如下

@X
public Service1 {
} 

我尝试了以下切入点定义,但它仅在@Y 在服务本身上时才有效,这意味着它看不到注释在 @X 上

@Around("@within(com.mypackage.Y)")

【问题讨论】:

  • 我试过用 \@annotation 替换 \@within 但这也不起作用。就好像注释根本看不到,而是aspectj,因为它在X注释上
  • 不知何故,我完全错误地阅读了您的问题。对不起:(

标签: java spring annotations aspectj spring-aop


【解决方案1】:

我在应用程序中有这个确切的需求。我找到了这个答案,但不满意这无法完成。

经过一番搜索,我找到了这个 cheat sheet 用于 AspectJ/Spring 切入点表达式。备忘单中的解决方案与宣传的不完全一样,但我能够让它满足我的需要。

@Pointcut("within(@(@Annotation *) *)")
public void classAnnotatedWithNestedAnnotationOneLevelDeep() { }

我将此表达式与 @within 表达式组合在一起,仅用于 @Annotation 以获得我想要的工作。

对于方法执行:

@Pointcut("execution(@(@com.someorg.SomeAnnotation *) * *(..))")
public void methodAnnotatedWithNestedAnnotationOneLevelDeep() { }

我将此表达式与 @annotation 表达式组合在一起,仅用于 @Annotation 以获得我想要为方法工作的内容。

【讨论】:

  • 酷,伙计!你是对的,我刚刚根据你所说的更新了我的答案。虽然我说注释不是继承是正确的,但实际上 AspectJ 可以使用您在此处描述的语法间接推断它们。我不再经常了解 AspectJ 的新知识了,但现在我才知道。
【解决方案2】:

这不是 Spring 或 AspectJ 问题。在 Java 中,接口上的注解、其他注解或方法永远不会通过实现类、使用注解注解的类或覆盖方法来继承。注解继承仅适用于从类到子类,但前提是超类中使用的注解类型带有元注解@Inherited

更新:因为我之前已经多次回答过这个问题,所以我刚刚在Emulate annotation inheritance for interfaces and methods with AspectJ 中记录了这个问题以及解决方法。

这是一个小证据,证明你想要的东西不起作用,因此也不能被某个方面利用:

package de.scrum_master.app;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface OuterAnnotation {}
package de.scrum_master.app;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@OuterAnnotation
public @interface InnerAnnotation {}
package de.scrum_master.app;

import java.lang.annotation.Annotation;

@InnerAnnotation
public class Application {
    public static void main(String[] args) {
        for (Annotation annotation : Application.class.getAnnotations())
            System.out.println(annotation);
    }
}

控制台输出显示 JVM 只看到内部注解,而不是用于内部注解的外部注解:

@de.scrum_master.app.InnerAnnotation()

更新: 对 Bradley M Handy 的回答很感兴趣,我重新检查了它是否也适用于我的代码中描述的情况,确实如此。这种类型的 AspectJ 语法对我来说是未知的,尽管我认为我对 AspectJ 了解很多。所以谢谢,布拉德利。 :-) 这方面会起作用:

package de.scrum_master.aspect;

import de.scrum_master.app.OuterAnnotation;

public aspect MetaAnnotationAspect {
  after() : within(@(@OuterAnnotation *) *) && execution(* *(..)) {
    System.out.println(thisJoinPoint);
  }
}

运行应用程序时的控制台日志:

@de.scrum_master.app.InnerAnnotation()
execution(void de.scrum_master.app.Application.main(String[]))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2011-12-10
    • 1970-01-01
    • 2023-01-27
    相关资源
    最近更新 更多