Spring AspectJ,方法执行前的切入点,其中注释了方法 OR 类 [英] Spring AspectJ, pointcut before method execution where method OR class is annotated

查看:44
本文介绍了Spring AspectJ,方法执行前的切入点,其中注释了方法 OR 类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过 Spring Aop AspectJ 样式获取注释的值,其中注释可以在类或方法上.我尝试了很多不同的东西,但只有当注释在方法上时我才能让它工作.我真的很想在类上注释 ONCE - 但建议类的所有方法 - 并在建议中访问类注释的值.这是我结束的地方:

I'm trying to get the value of an annotation via Spring Aop AspectJ-style, where the annotation can be on the class OR the method. I tried a lot of different things, but I can only get it to work when the annotation is on the method. I'd really like to annotate ONCE on the class - but advice all the methods of the class - and access the value of the class annotation in the advice. Here's where I've ended up:

注释:

@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) {
        ...
    }
}

有什么想法吗?谢谢.

推荐答案

简短回答

虽然您可以制定一个切入点,同时匹配两者直接注释的方法注释类型的方法,但您不能使您绑定注释值的切入点和/或通知(即在通知代码中使用注释值).

Short answer

While you can formulate a pointcut that will match both directly annotated methods and methods of annotated types at the same time, you cannot make a pointcut and/or advice where you bind the value of the annotation (i.e. use the annotation value in the advice code).

@Aspect
public class MyAspect {

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

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

    @Before("atExecutionOfAnnotatedMethod() && @annotation(myAnnotation)")
    public void myAdviceForMethodAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        System.out.println("myAdviceForMethodAnnotation: " + myAnnotation.value());
    }

    @Before("atExecutionOfMethodsOfAnnotatedClass() && @this(myAnnotation)")
    public void myAdviceForTypeAnnotation(JoinPoint joinPoint, MyAnnotation myAnnotation) {
        System.out.println("myAdviceForTypeAnnotation: " + myAnnotation.value());
    }

    //      /* the following pointcut will result in "inconsistent binding" errors */
    //      @Pointcut("(atExecutionOfAnnotatedMethod() && @annotation(myMethodAnnotation)) || (atExecutionOfMethodsOfAnnotatedClass() && @this(myTypeAnnotation))")
    //      public void combinedPointcut(MyAnnotation myMethodAnnotation, MyAnnotation myTypeAnnotation) {}

}

一些细节

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

Some detail

To combine the two separate pointcuts (atExecutionOfAnnotatedMethod and atExecutionOfMethodsOfAnnotatedClass) we would have to use the OR (||) construct. Since the OR construct doesn't guarantee that either of the two annotation bindings will be present at advice execution, they will both result in a compile error (inconsistent binding). You can still handle both cases in separate advices, you may also delegate the actual advice code to a common method to avoid duplication. In that case you'll need to take care of the case where both the type and the method is annotated with @MyAnnotation because that would match both pointcuts and would result in your method doubly advised by both advices, hence your common advice handling code will execute twice.

如果需要将两种情况结合起来,同时防止双重通知目标代码,则需要在方法级注解和类级注解之间设置优先级.基于特殊性原则,我建议走方法级注释优先于类一级注释的路线.您的方面将如下所示:

If you need to combine the two cases while defending against doubly advising the target code, you need to set up a precedence between the method level annotation and the class level annotation. Based on the principle of specificity, I'd suggest to go on the route where the method level annotation takes precedence over the class level one. Your aspect would look like this:

@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());
    }

这篇关于Spring AspectJ,方法执行前的切入点,其中注释了方法 OR 类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆