AspectJ OR 运算符似乎不起作用 [英] AspectJ OR Operator Doesn't Seem to be Functioning

查看:28
本文介绍了AspectJ OR 运算符似乎不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm having a little trouble getting a logging aspect set up using SpringAOP + AspectJ. I would like an "Around" method to fire when either a class or method is annotated with the @Loggable annotation. Below is my advice code:

@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 没有,这是我真正想要的.关于为什么会这样的任何想法?

test1 and test2 fire. test3 does not, and it's the one that I really want. Any thoughts on why this might be?

推荐答案

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

First of all, there are syntax errors in your pointcuts. It is not lower-case argnames but argNames and you are missing an = in between parameter name and value. So it must be argNames = "bean, loggable".

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

Secondly if your advice returns void it will only match methods returning void as well. The more general case is to return Object in the advice to really match all methods.

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

Last but not least, you should see a warning which explains the problem with the third pointcut. This is displayed in your Eclipse IDE or on the AspectJ compiler's (ajc) log output:

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

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

This means that you cannot say "bind one value or the other to the parameter 'loggable'". What if both conditions match? Which one should be assigned? You have two options, assuming your fully-qualified class name is de.scrum_master.app.Loggable:

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

A) No reference to @Loggable annotation needed:

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

This is the simple case. If @Loggable does not have any parameters you need to read, it is not necessary to bind it to a parameter. BTW, if you want your pointcut to also capture static methods, you should not bind target() either because the target would be null. Maybe in Spring-AOP this is irrelevant because it only works with Spring Beans anyway, but in full-featured AspectJ it would make a difference because it is more powerful.

@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 注释:

B) Reference to @Loggable annotation needed:

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

You have no other choice than to go with two separate pointcuts if you want to bind the annotations to parameters. Maybe you could use a utility method doing the actual logging in order to avoid code duplication in your advice.

这篇关于AspectJ OR 运算符似乎不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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