Spring AOP не может использовать двойную аннотацию - PullRequest
0 голосов
/ 21 января 2019

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

@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 is null .

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

  1. При получении на уровне метода, отличном от retry is null .
  2. При обнаружении на уровне класса retry is переплет .

Родительская версия Spring Boot- 2.1.1. РЕЛИЗ

1 Ответ

0 голосов
/ 22 января 2019

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

Прагматично я (хотел бы) решить (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).

...