【问题标题】:AspectJ OR Operator Doesn't Seem to be FunctioningAspectJ OR 运算符似乎不起作用
【发布时间】:2014-09-29 15:32:16
【问题描述】:

我在使用 SpringAOP + AspectJ 设置日志记录方面时遇到了一点麻烦。我希望在使用 @Loggable 注释对类或方法进行注释时触发“Around”方法。以下是我的建议代码:

@Around(value = "execution( * *(..)) && target(bean) && @annotation(loggable)", argnames "bean, loggable")
public void test1(ProceedingJoinPoint method, Object bean, Loggable loggable) { }

@Around(value = "execution( * *(..)) && target(bean) && @within(loggable)", argnames "bean, loggable")
public void test2(ProceedingJoinPoint method, Object bean, Loggable loggable) { }

@Around(value = "execution( * *(..)) && target(bean) && (@annotation(loggable) || @within(loggable))", argnames "bean, loggable")
public void test3(ProceedingJoinPoint method, Object bean, Loggable loggable) { }

test1 和 test2 着火。 test3 没有,它是我真正想要的。关于为什么会这样的任何想法?

【问题讨论】:

    标签: aop aspectj spring-aop


    【解决方案1】:

    首先,您的切入点存在语法错误。它不是小写的argnames,而是argNames,您在参数名称和值之间缺少=。所以一定是argNames = "bean, loggable"

    其次,如果您的建议返回 void,它也只会匹配返回 void 的方法。更一般的情况是在通知中返回Object 以真正匹配所有方法。

    最后但并非最不重要的一点是,您应该会看到一个警告,它解释了第三个切入点的问题。这显示在您的 Eclipse IDE 或 AspectJ 编译器的 (ajc) 日志输出中:

    ambiguous binding of parameter(s) loggable across '||' in pointcut
    

    这意味着您不能说“将一个值或另一个绑定到参数'loggable'”。如果两个条件都匹配怎么办?应该分配哪一个?您有两个选择,假设您的完全限定类名是de.scrum_master.app.Loggable

    A) 不需要引用 @Loggable 注释:

    这是一个简单的例子。如果@Loggable 没有任何需要读取的参数,则无需将其绑定到参数。顺便说一句,如果你希望你的切入点也捕获静态方法,你也不应该绑定target(),因为目标是null。也许在 Spring-AOP 中这无关紧要,因为无论如何它只适用于 Spring Beans,但在功能齐全的 AspectJ 中它会有所作为,因为它更强大。

    @Around(value = "execution(* *(..)) && (@annotation(de.scrum_master.app.Loggable) || @within(de.scrum_master.app.Loggable))")
    public Object withoutLoggableReference(ProceedingJoinPoint thisJoinPoint) {
        Object bean = thisJoinPoint.getTarget();
        System.out.println(thisJoinPoint + " -> " + bean);
        return thisJoinPoint.proceed();
    }
    

    或者,等效地:

    @Around(value = "execution(* (@de.scrum_master.app.Loggable *.*)(..)) || execution(@de.scrum_master.app.Loggable * *.*(..))")
    public Object withoutLoggableReference(ProceedingJoinPoint thisJoinPoint) {
        Object bean = thisJoinPoint.getTarget();
        System.out.println(thisJoinPoint + " -> " + bean);
        return thisJoinPoint.proceed();
    }
    

    B) 需要引用@Loggable 注释:

    如果你想将注解绑定到参数,你别无选择,只能使用两个单独的切入点。也许您可以使用实用方法进行实际日志记录,以避免您的建议中出现代码重复。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 1970-01-01
      • 2017-07-28
      • 1970-01-01
      • 2015-02-26
      • 1970-01-01
      • 2018-12-28
      相关资源
      最近更新 更多