You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

@Around Advice无法作用于包级注解的问题解决咨询

解决包级@LogAPIVersion注解拦截器不生效的问题

问题原因

Spring AOP的默认切点逻辑只会识别方法、类级别的注解,不会主动读取package-info.java中的包级注解,所以直接在包上标注注解时,拦截器无法触发。需要手动在切面中添加包注解的检测逻辑。

解决方案

1. 编写包注解读取工具类

用来读取目标类所在包的package-info中的注解:

import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;

import java.io.IOException;
import java.lang.annotation.Annotation;

public class PackageAnnotationUtils {
    public static <A extends Annotation> A getPackageAnnotation(Class<?> targetClass, Class<A> annotationClass) {
        String packageName = targetClass.getPackage().getName();
        String packageResourcePath = ClassUtils.convertClassNameToResourcePath(packageName) + "/package-info.class";
        
        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(new PathMatchingResourcePatternResolver());
        try {
            MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(packageResourcePath);
            return metadataReader.getAnnotationMetadata().getAnnotationAttributes(annotationClass.getName()) != null
                    ? annotationClass.cast(metadataReader.getAnnotationMetadata().getAnnotation(annotationClass))
                    : null;
        } catch (IOException e) {
            // 无package-info文件时返回null
            return null;
        }
    }
}

2. 修改切面逻辑,整合包注解检测

在原来的切面方法中,补充包级注解的检查逻辑,覆盖方法、类、包三种注解场景:

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 LogAPIVersionAspect {

    @Around("@annotation(logAPIVersion) || @within(logAPIVersion)")
    public Object logAPIVersion(ProceedingJoinPoint joinPoint, LogAPIVersion logAPIVersion) throws Throwable {
        // 方法/类上无注解时,尝试读取包级注解
        if (logAPIVersion == null) {
            Class<?> targetClass = joinPoint.getTarget().getClass();
            logAPIVersion = PackageAnnotationUtils.getPackageAnnotation(targetClass, LogAPIVersion.class);
        }
        
        // 存在有效注解时,执行日志添加API版本的逻辑
        if (logAPIVersion != null && !logAPIVersion.apiVersion().isEmpty()) {
            String apiVersion = logAPIVersion.apiVersion();
            // 这里替换成你的日志处理逻辑,比如MDC.put("apiVersion", apiVersion);
            // 示例:打印API版本
            System.out.printf("当前请求API版本:%s%n", apiVersion);
        }
        
        return joinPoint.proceed();
    }
}

3. 额外检查事项

  • 确保package-info.java被正确编译:大部分构建工具(Maven/Gradle)默认会编译该文件,若有自定义构建规则,需确认未排除它。
  • 切面类需被Spring扫描:确保LogAPIVersionAspect上的@Component注解生效,且所在包在Spring Boot的@SpringBootApplication扫描范围内。

内容的提问来源于stack exchange,提问作者goutham

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:45:42