@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
相关产品推荐
相关产品推荐

