Spring - AOP: @within Exception: java.lang.IllegalArgumentException: error Type referenced is not an annotation type

Spring - AOP: @within Exception: java.lang.IllegalArgumentException: error Type referred to is not an annotation type

我是 AOP 和 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
    }
}

注释class(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[=15=](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)

我没有尝试 运行 你的代码,但我一眼就注意到了两件事:

  • BeanCreationException 对于内部 Spring 类型,如果方面切入点太宽泛,通常会出现方面,即方面也被编织到(即使没有执行)Spring 类。在这种情况下,您希望通过向切入点添加类似 ... && within(my.package..*) 的内容来限制方面范围。或者,如果您的方面在库中可能 运行 与未知的包名称有关,您可以排除 Spring 包或 类 导致 !within(org.springframework..*) 或任何适用的包名称出现问题在你的情况下。另见 .

  • 您的 @Around 建议 return 和 void,即它也只会匹配 void 方法,这可能不是您想要的。为了匹配非 void 方法,建议必须 return 除了 void 之外的东西,如果你想匹配任何 return 类型,通常只是 Object。还要确保您 return proceed() 的结果或您想要 returned 的任何其他结果。