spring 如何防止Sping Boot AOP删除类型注解?

e5nszbig  于 2023-03-16  发布在  Spring
关注(0)|答案(2)|浏览(174)

我对 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;
    }
}

我应该如何排除故障?

5cnsuln7

5cnsuln71#

如何防止Sping Boot AOP删除类型注解?
Sping Boot 没有删除任何东西,但是Spring AOP使用运行时生成的动态代理,即子类或接口实现,带有事件钩子(连接点),用于通过切入点连接的方面建议代码。默认情况下,注解不会被继承,因此这只是JVM的一个特性。
继承父类注解的子类有一个例外:您可以将 meta注解@Inherited添加到您自己的注解类GreetingsMeta中,其效果是,如果您用它来注解任何类,那么所有子类(以及Spring AOP创建的动态代理)都将继承该注解,并且您的原始代码应该按预期运行。
因此,在这种情况下,不需要使用 JC Carrillo 建议的AnnotationUtils。当然,他的方法也有效。只是AnnotationUtils更复杂,因为AnnotationUtils在内部使用了大量反射魔法和帮助类来计算结果。因此,我只会在不直接注解类而注解方法或接口的情况下使用AnnotationUtils,因为@Inherited对它们没有任何影响。或者,如果您依赖于Spring(或自己的) meta注解(注解上的注解)的层次结构,并且您需要将它们合并为一个来获取信息,那么AnnotationUtilsMergedAnnotations是合适的。

bpzcxfmw

bpzcxfmw2#

您可能需要查看AnnotationUtils

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

相关问题