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

查看:94
本文介绍了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.

如果在防止双重建议目标代码的同时需要结合这两种情况,则需要在方法级别注释和类级别注释之间设置优先级.基于特定性原则,我建议您继续使用方法级别注释优先于类级别1的方法.您的方面将如下所示:

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天全站免登陆