Как запретить Spring Boot AOP удалять аннотации типов? - PullRequest
1 голос
/ 21 апреля 2020

Я довольно новичок в Spring Boot и его разновидности AOP, но не новичок в программировании на других языках и средах AOP. Это одна проблема, я не уверен, как решить.

У меня есть простой декоратор метаданных:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GreetingsMeta {
    public float version() default 0;
    public String name() default "";
}

Он отлично работает с внедрением зависимостей:

public GreetingController(List<IGreetingService> greetings) throws Exception {
    this.greetings = new HashMap<>();
    greetings.forEach(m -> {
        Class<?> clazz = m.getClass();
        if (clazz.isAnnotationPresent(GreetingsMeta.class)) {
            GreetingsMeta[] s = clazz.getAnnotationsByType(GreetingsMeta.class);
            this.greetings.put(s[0].name(), m);
        }
    });
}

Пока я не применил стандартный аспект ведения журнала:

@Aspect
@Component
public class LoggingAspect {
    @Around("execution(* com.firm..*(..)))")
    public Object profileAllMethods(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        String methodName = methodSignature.getName();
        final StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Object result = joinPoint.proceed();
        stopWatch.stop();
        LogManager.getLogger(methodSignature.getDeclaringType())
        .info(methodName + " " + (stopWatch.getTotalTimeSeconds() * 1000) + " µs");
        return result;
    }
}

Тогда список аннотацийData становится пустым, даже аннотация @Component исчезла.

Пример мета-оформленного класса:

@Component
@GreetingsMeta(name = "Default", version = 1.0f)
public class DefaultGreetingsService implements IGreetingService {


    @Override
    public String message(String content) {
        return "Hello, " + content;
    }
} 

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

Ответы [ 2 ]

2 голосов
/ 23 апреля 2020

Как запретить Spring Boot AOP удалять аннотации типов?

Spring Boot ничего не удаляет, но для Spring AOP используются динамические c прокси, созданные во время выполнения, т.е. подклассы или реализации интерфейса с перехватчиками событий (joinpoints) для кода подсказки аспекта, связанного через pointcuts. По умолчанию аннотации не наследуются, поэтому это всего лишь функция JVM.

Существует одно исключение для подклассов, наследующих аннотации от родительских классов: вы можете добавить метааннотацию @Inherited в ваш собственный класс аннотаций GreetingsMeta. Результатом будет то, что если вы аннотируете какой-либо класс с ним, все подклассы (также динамические c прокси, созданные Spring AOP) будут наследовать аннотацию, и ваш исходный код должен работать так, как ожидается.

Так что в этом случае нет необходимости использовать AnnotationUtils, как предложено J C Carrillo . Его подход тоже работает, конечно. Это просто сложнее, потому что AnnotationUtils использует много магических отражений c и множество вспомогательных классов для вычисления результатов. Таким образом, я бы использовал AnnotationUtils только в тех случаях, когда вы напрямую не аннотируете класс, а, например, методы или интерфейсы, потому что @Inherited не влияет на них, как описано в документации. Или, если вы полагаетесь на иерархию мета-аннотаций Spring (или собственных) (аннотации на аннотации), и вам необходимо получить информацию от них, объединенных в одну, AnnotationUtils или MergedAnnotations являются подходящими.

1 голос
/ 22 апреля 2020

Возможно, вы захотите посмотреть AnnotationUtils

Method method = methodSignature.getMethod();
GreetingsMeta greetingsMeta = AnnotationUtils.findAnnotation(method, GreetingsMeta.class);
...