Spring AOP не может дважды связать аннотацию

У меня есть аннотация:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Retry {

    int DEFAULT_RETRIES = 2;

    int times() default DEFAULT_RETRIES;
}

Который используется либо на уровне класса:

@Retry(times = 5)
public class PersonServiceClass {

//...

    public void deletePerson(long id) {
        //...
    }
}

Или уровень метода (другой класс, а не PersonServiceClass):

@Retry
public void deletePerson(long id) {
    //...
}

Аспект ловится таким классом:

@Aspect
@Component
public class RetryInterceptor {

    @Around("@within(retry) || @annotation(retry)")
    public Object around(ProceedingJoinPoint proceedingJoinPoint, Retry retry) throws Throwable {
        System.out.println("around - " + retry);
        System.out.println("joinpoint - " + proceedingJoinPoint);
        return aroundHandler(proceedingJoinPoint, retry);
    }

И аспект правильно перехватывается на уровне метода или класса, но что-то не так с привязкой аннотации Retry.

Когда @Around выглядит следующим образом: @Around("@within(retry) || @annotation(retry)"), тогда:

  1. При обнаружении на уровне метода retry имеет значение связанный.
  2. При обнаружении на уровне класса retry имеет значение нулевой.

Когда @Around выглядит следующим образом @Around("@annotation(retry) || @within(retry)"), тогда:

  1. При обнаружении на уровне метода retry имеет значение нулевой.
  2. При обнаружении на уровне класса retry имеет значение связанный.

Родительская версия Spring Boot — 2.1.1.RELEASE

Вы «пытались» использовать (неэффективный) | (или, который оценивает обе стороны) вместо || («эффективный»)? ...может это не баг, а фича!? :)

xerx593 21.01.2019 14:54

"|" недействительный токен

mat.mik 22.01.2019 10:24

... да, это был гатшот: || && ! - единственные операнды...

xerx593 22.01.2019 10:36
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
3
222
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

...теперь ты бросил мне вызов :) и я может воспроизвести проблему!

Прагматически я (бы) решил (d) это так:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class ExampleAspect {

  @Around("@within(retry)")
  public Object typeAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
    return commonAspect(joinPoint, retry);
  }

  @Around("@annotation(retry)")
  public Object methodAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
    return commonAspect(joinPoint, retry);
  }

  private Object commonAspect(ProceedingJoinPoint joinPoint, Retry retry) throws Throwable {
    System.out.println("Retry is :" + (retry == null ? "null" : retry.value()));
    // ... do your (common) stuff here
    return proceed;
  }

}

..Добро пожаловать! :-)

А так как у вас уже есть (распространенный) метод aroundHandler(), то сводится к тому, чтобы "ввести для него 2 общедоступных фасада/PCD".

Дополнительный совет: переименуйте times() (если это единственное/основное свойство этой аннотации) в: value()! .. тогда вы можете сделать "просто" @Retry(100).

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