AspectJ OR运算符似乎不起作用

时间:2014-09-29 15:32:17

标签: aspectj spring-aop

我在使用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没有,这是我真正想要的那个。有关为什么会这样的想法吗?

1 个答案:

答案 0 :(得分: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注释:

如果要将注释绑定到参数,除了使用两个单独的切入点之外别无选择。也许您可以使用实用程序方法进行实际日志记录,以避免在您的建议中重复代码。