2014-09-29 2 views
0

У меня возникли проблемы с настройкой ведения журнала, используя SpringAOP + AspectJ. Я бы хотел, чтобы метод «Around» запускался, когда аннотируется класс или метод с помощью аннотации @Loggable. Ниже приведен код моего совета:AspectJ OR Operator не работает

@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) { } 

тест1 и тест2 огонь. test3 нет, и это тот, который я действительно хочу. Любые мысли о том, почему это может быть?

ответ

1

Прежде всего, в ваших точечных сообщениях есть синтаксические ошибки. Это не нижний регистр argnames, а argNames, и вам не хватает = между именем и значением параметра. Так должно быть argNames = "bean, loggable".

Во-вторых, если ваш совет возвращает void, он будет соответствовать методам, возвращающим void. Более общий случай - вернуть Object в совет, чтобы действительно соответствовать всем методам.

И последнее, но не менее важное: вы должны увидеть предупреждение, которое объясняет проблему с третьим pointcut. Это отображается в вашем Eclipse IDE или на AspectJ компилятора (AJC) журнал выхода:

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

Это означает, что вы не можете сказать «привязать одно значение или другой для параметра" loggable». Что делать, если оба условия совпадают? Какой из них нужно назначить? У вас есть два варианта, предполагается, что ваш полное имя класса не de.scrum_master.app.Loggable:

A) Нет ссылки на @Loggable аннотацию необходимо:

Это простой случай. Если @Loggable не имеет параметров, которые необходимо прочитать, нет необходимости привязывать его к параметру. BTW, если вы хотите, чтобы ваш pointcut также фиксировал статические методы, вы не должны связывать 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 аннотаций необходимо:

У вас нет другого выбора, кроме как идти с двумя отдельными срезов в, если вы хотите привязать аннотации к параметрам. Возможно, вы могли бы использовать метод утилиты, выполняющий фактическое ведение журнала, чтобы избежать дублирования кода в ваших советах.