Spring AOP: совет по аннотации используется поверх другого совета

Я создал свою собственную аннотацию:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Condition {
    String value();
}

Я хочу использовать эту аннотацию, чтобы определить, следует ли запустить совет, моя попытка:

@Condition("some.config")
@Around("execution(public * someMethod())")
Object doSomething(ProceedingJoinPoint joinPoint) throws Throwable {
    // some logic here
}

@Around("@annotation(condition)")
Object checkCondition(ProceedingJoinPoint joinPoint, Condition condition) throws Throwable {
    String property = (String) configuration.getProperty(condition.value());
    if (Boolean.valueOf(property)){
        return joinPoint.proceed();
    } else {
        return null;
    }
}

Работает когда использую @Condition на некоторых других методах, т.е. checkCondition применяется, а затем метод выполняется или не на основе значения конфигурации. За советом doSomething это не применяется, хотя.

1 ответ

Решение

Вы сказали, что ваш аспект работает для других компонентов, но не для самого аспекта. Из этого заявления я понимаю, что

  1. ваш аспект подключен правильно (например, помечены @Component и обнаружен при сканировании компонента или подключен вручную через XML-конфигурацию) и
  2. Вы используете Spring AOP на основе прокси.

В (2) источник вашей проблемы. Согласно руководству Spring сами аспекты освобождаются от того, чтобы сами быть аспектными объектами:

Консультирование аспектов с другими аспектами?

В Spring AOP невозможно, чтобы сами аспекты были целью советов других аспектов. Аннотация @Aspect для класса помечает его как аспект и, следовательно, исключает его из автоматического проксирования.

Таким образом, М. Прохоров в некоторой степени ошибается, когда говорит, что аспекты не являются (или не могут быть) компонентами Spring, но он прав, поскольку по своему замыслу вы не можете самостоятельно советовать какой-либо аспект или советовать другим аспектам. Его предположение, что оно может работать с AspectJ, также верно. Он работает с AspectJ, поэтому, если вам это нужно, вы можете настроить Spring для использования AspectJ через LTW вместо Spring AOP для этого случая.

Другие вопросы по тегам