我在使用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没有,这是我真正想要的那个。有关为什么会这样的想法吗?
答案 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
注释:
如果要将注释绑定到参数,除了使用两个单独的切入点之外别无选择。也许您可以使用实用程序方法进行实际日志记录,以避免在您的建议中重复代码。