SpringAspectJ,方法执行前的切入点,其中方法或类被注释

SpringAspectJ,方法执行前的切入点,其中方法或类被注释,spring,aspectj,spring-aop,Spring,Aspectj,Spring Aop,我试图通过Spring Aop AspectJ样式获取注释的值,其中注释可以位于类或方法上。我尝试了很多不同的方法,但只有在方法上有注释时,我才能让它工作。我真的很想在类上注释一次,但建议类的所有方法,并在建议中访问类注释的值。这就是我的结局: 注释: @Inherited @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotati

我试图通过Spring Aop AspectJ样式获取注释的值,其中注释可以位于类或方法上。我尝试了很多不同的方法,但只有在方法上有注释时,我才能让它工作。我真的很想在类上注释一次,但建议类的所有方法,并在建议中访问类注释的值。这就是我的结局:

注释:

@Inherited
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value() default "";
}
方面:

@Aspect
public class MyAspect {
    @Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
    public void atExecution() { }

    @Before("atExecution() && @annotation(myAnnotation)")
    public void myAdvice(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        ...
    }
}
有什么想法吗?谢谢。

简短回答 虽然您可以制定一个切入点,该切入点将同时匹配直接注释的方法和注释类型的方法,但您不能在绑定注释值(即在注释代码中使用注释值)的位置生成切入点和/或建议

一些细节 要组合两个单独的切入点(
ATExecutionFannotatedMethod
ATExecutionOfMethodsofNotatedClass
),我们必须使用OR(
|
)构造。由于OR构造不能保证两个注释绑定中的任何一个在通知执行时出现,因此它们都会导致编译错误(绑定不一致)。 您仍然可以在单独的通知中处理这两种情况,也可以将实际的通知代码委托给一个通用方法以避免重复。在这种情况下,您需要注意类型和方法都使用
@MyAnnotation
进行注释的情况,因为这将匹配两个切入点,并将导致您的方法被两个通知双重通知,因此您的通用通知处理代码将执行两次

两者结合 如果需要将这两种情况结合起来,同时避免双重通知目标代码,则需要在方法级注释和类级注释之间设置优先级。基于特殊性原则,我建议继续采用方法级注释优先于类级注释的方法。您的外观如下所示:

@Aspect
public class MyCombinedAspect {

    @Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
    public void atExecutionOfAnnotatedMethod() {}

    @Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
    public void atExecutionOfMethodsOfAnnotatedClass() {}

    @Before("atExecutionOfAnnotatedMethod() && !atExecutionOfMethodsOfAnnotatedClass() && @annotation(myAnnotation)")
    public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        handleBeforeExecution(joinPoint, myAnnotation);
    }

    @Before("atExecutionOfMethodsOfAnnotatedClass() && !atExecutionOfAnnotatedMethod() && @this(myAnnotation)")
    public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        handleBeforeExecution(joinPoint, myAnnotation);
    }

    @Before("atExecutionOfMethodsOfAnnotatedClass() && atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)")
    public void myAdviceForDoublyAnnotated(JoinPoint joinPoint, MyAnnotation myMethodAnnotation) {
        handleBeforeExecution(joinPoint, myMethodAnnotation);
    }

    protected void handleBeforeExecution(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        System.out.println(myAnnotation.value());
    }

谢谢你的回复。非常详细。所以我想澄清一下。我可以用两个不同的建议来做这件事,但是需要注意不要同时注释类和方法。(这将很难执行)。再次感谢!不,让我澄清一下。注释类或方法就足够了。但是我们不能强制开发人员不同时注释类和方法。在这种情况下,我们希望方法注释生效。因此,我们有3条建议来处理3种情况,顺序是:1-当仅对方法进行注释时,2-当仅对类进行注释时,3-当对方法和类进行注释时,在这种情况下,方法注释的值传递给委托方法。这三个建议都代表了同样的方法来做这项工作,坚持干燥的原则。我的回答中的第二个方面与我在之前的评论中描述的方式相同。希望这能消除最终的困惑,明白了。再次感谢所有的细节。真的很有帮助。
@Aspect
public class MyCombinedAspect {

    @Pointcut("execution(@com.myco.MyAnnotation * com.myco.somepackage..*.*(..))")
    public void atExecutionOfAnnotatedMethod() {}

    @Pointcut("execution(* (@com.myco.MyAnnotation com.myco.somepackage..*).*(..))")
    public void atExecutionOfMethodsOfAnnotatedClass() {}

    @Before("atExecutionOfAnnotatedMethod() && !atExecutionOfMethodsOfAnnotatedClass() && @annotation(myAnnotation)")
    public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        handleBeforeExecution(joinPoint, myAnnotation);
    }

    @Before("atExecutionOfMethodsOfAnnotatedClass() && !atExecutionOfAnnotatedMethod() && @this(myAnnotation)")
    public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        handleBeforeExecution(joinPoint, myAnnotation);
    }

    @Before("atExecutionOfMethodsOfAnnotatedClass() && atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)")
    public void myAdviceForDoublyAnnotated(JoinPoint joinPoint, MyAnnotation myMethodAnnotation) {
        handleBeforeExecution(joinPoint, myMethodAnnotation);
    }

    protected void handleBeforeExecution(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        System.out.println(myAnnotation.value());
    }