Spring - AOP: @within Exception: java.lang.IllegalArgumentException: указанный тип ошибки не является типом аннотации

Я новичок в АОП и AspectJ. Я пытаюсь написать собственную логику для пользовательской аннотации с типом элемента TYPE. Я также хочу использовать параметры в моей аннотации, чтобы написать собственную логику внутри метода around. Я получаю указанную ниже ошибку. Я пробовал читать несколько источников, и большинство из них связано с использованием @annotation. Мне трудно понять то же самое. Может кто-нибудь объяснить, почему следующий способ с @within не работал с каким-то ясным примером?

Аннотация (Slf4jTrace.java):

package io.ud.project.falcon.logging;

import io.ud.project.falcon.logging.generator.AbstractLogTraceIdGenerator;
import io.ud.project.falcon.logging.generator.DefaultLogTraceIdGenerator;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Slf4jTrace {

    String traceKey() default "traceId";

    Class<? extends AbstractLogTraceIdGenerator> traceValueGenerator() default DefaultLogTraceIdGenerator.class;

}

Компонент аспекта (Slf4jTraceAspect.java):

package io.ud.project.falcon.logging;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
@SuppressWarnings("unused")
@Slf4j
public class Slf4jTraceAspect {

    @Pointcut("execution(public * *(..))")
    public void publicOperation() {
        //Using this pointcut annotation for Around method.
    }

    @Around(value = "@within(slf4jTrace) && publicOperation()")
    public void logTrace(ProceedingJoinPoint joinPoint, Slf4jTrace slf4jTrace) throws Throwable {
        //Custom logic that uses slf4jTrace's parameters        
        joinPoint.proceed();
        //Custom logic that uses slf4jTrace's parameters
    }
}

Аннотированный класс (Foo.java):

package io.ud.project.falcon.logging;

import io.ud.project.falcon.logging.Slf4jTrace;

@Slf4jTrace(traceKey = "auditID")
public class Foo {

    public void doSomething() {
        //Something happens here.
    }

}

Ошибка при запуске приложения:

, 2021-01-02 22:16:41,340, ERROR [main] o.s.b.SpringApplication.reportFailure(833) | Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'objectMapperConfigurer' defined in springfox.documentation.spring.web.SpringfoxWebMvcConfiguration
: BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': BeanPostProcessor before instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.cache.annotation.ProxyCachingConfiguration': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error Type referred to is not an annotation type: slf4jTrace
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:497)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205)
        at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:238)
        at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:709)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:534)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234)
        at io.ud.project.falcon.FalconApplication.main(FalconServiceApplication.java:65)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:48)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:87)
        at org.springframework.boot.loader.Launcher.launch(Launcher.java:50)
        at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:51)

person Udayabharathi Thiagarajan    schedule 02.01.2021    source источник
comment
Ваши коды работают. Можете поделиться objectMapperConfigurer может проблема в этом?   -  person ismail durmaz    schedule 02.01.2021
comment
Привет, извините, я не вставляю вручную bean-компонент типа objectMapperConfigurer в код.   -  person Udayabharathi Thiagarajan    schedule 03.01.2021


Ответы (1)


Я не пробовал запускать ваш код, но, взглянув на него, сразу заметил две вещи:

  • BeanCreationException для внутренних типов Spring часто возникает, если точки разреза аспектов слишком широки, т.е. аспекты также вплетаются в классы Spring (даже если не выполняются в них). В таких случаях вы хотите ограничить область видимости, добавив что-то вроде ... && within(my.package..*) в свой pointcut. В качестве альтернативы, если ваш аспект находится в библиотеке, потенциально работающей с неизвестными именами пакетов, вы можете исключить пакеты или классы Spring, вызывающие проблемы из-за !within(org.springframework..*) или любых других имен пакетов, применимых в вашем случае. См. Также мой ответ здесь.

  • Ваш @Around совет возвращает void, т.е. он также будет соответствовать только void методам, что, вероятно, не то, что вам нужно. Чтобы сопоставить непустые методы, совет должен возвращать что-то другое, кроме void, обычно просто Object, если вы хотите сопоставить любой тип возвращаемого значения. Также убедитесь, что вы возвращаете результат proceed() или любой другой результат, который вы хотите вернуть.

person kriegaex    schedule 03.01.2021
comment
Хорошо, я хотел иметь это как библиотеку, поэтому обязательно буду использовать !within(org.springframework..*). Что касается вашего второго пункта, я хочу сопоставить как void, так и non-void методы, и это причина того, что мой совет @Around недействителен. Пожалуйста, скажите мне, если это действительно неправильный дизайн, я исправлю его. Позвольте мне попробовать !within() и ответить. Спасибо! - person Udayabharathi Thiagarajan; 03.01.2021
comment
Не могли бы вы доложить, как обещали? Я хотел бы убедиться, что мы сможем закрыть этот вопрос. Он отмечен как открытый, потому что вы еще не приняли ни одного ответа. - person kriegaex; 08.01.2021
comment
Да, ваши очки действительно помогли. Большое спасибо. Что касается моего вопроса о получении экземпляра аннотации для pointcut, который находится в классе, имеющем аннотацию. Я все еще ничего не мог с собой поделать. В качестве обходного пути я использовал отражение, чтобы получить экземпляр, как показано ниже. Можете ли вы сказать, есть ли способ лучше? @Around("@within(com.tcl.common.util.logging.slf4jtrace.annotation.Slf4jTrace) && publicOperation()") public Object logTrace(ProceedingJoinPoint joinPoint) ... как совет и внутри метода совета, я сделал вот так joinPoint.getTarget().getClass().getAnnotation(Slf4jTrace.class) - person Udayabharathi Thiagarajan; 09.01.2021
comment
Вы ничего не спрашивали об использовании аннотаций. Согласно вашему образцу кода вы уже знаете, как привязать аннотацию к параметру метода совета. Нет необходимости использовать отражение, если вы просто следуете своему собственному образцу кода. Я только что объяснил вам, что не так в другом месте. @within(slf4jTrace) ... в сочетании с public Object logTrace(ProceedingJoinPoint joinPoint, Slf4jTrace slf4jTrace) - это правильный путь. Почему вы это изменили? Я не говорил тебе об этом. - person kriegaex; 10.01.2021
comment
Да, но когда я попытался сделать то же самое, как я уже упоминал в вопросе, я получил ту же следующую ошибку java.lang.IllegalArgumentException: error Type referred to is not an annotation type: slf4jTrace. - person Udayabharathi Thiagarajan; 10.01.2021
comment
Мы говорим мимо друг друга, и я не могу читать ваши мысли. Сначала вы сказали, что мои подсказки вам помогли, а теперь говорите, что у вас та же проблема, что и раньше. Я предлагаю вам опубликовать полную версию MCVE на GitHub и показать мне ее. С неполной и противоречивой информацией я не могу вам помочь. - person kriegaex; 10.01.2021
comment
Я принял ваш ответ, так как смог решить эту проблему с помощью предоставленных баллов. Что касается этого IllegalArgumentException, я попытался воспроизвести, но не смог. Теперь он работает должным образом с @within(slf4jTrace) ... в сочетании с public Object logTrace(ProceedingJoinPoint joinPoint, Slf4jTrace slf4jTrace) - person Udayabharathi Thiagarajan; 11.01.2021