Spring项目下如何编写方法判断类是否被任意注解修饰?
Spring环境下判断指定类是否被任意注解修饰的实现方案
核心思路
不需要引入Google Reflections等第三方反射库,直接使用Spring自带的ClassPathScanningCandidateComponentProvider类路径扫描工具,不需要提前指定具体注解类型,读取类的元数据后直接判断类上的注解数量即可完成校验,和Spring环境兼容性更高。
具体实现逻辑
- 初始化扫描器时关闭默认过滤器,避免只扫描Spring托管的组件类,保证可以覆盖指定包下的所有类
- 给扫描器添加自定义
TypeFilter,直接获取类上的所有注解信息,可根据需求选择是否过滤JDK自带的基础注解 - 扫描指定包路径后获取所有符合条件的类集合,判断目标类是否在集合中即可得到结果
代码实现
import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.TypeFilter; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.AnnotationMetadata; import java.io.IOException; import java.util.Set; import java.util.stream.Collectors; import org.springframework.beans.factory.config.BeanDefinition; public class AnnotationCheckUtils { /** * 判断指定类是否被任意注解修饰 * @param targetClass 待校验的目标类 * @param scanPackage 扫描的根包路径,支持多个包用逗号分隔 * @param excludeJdkAnnotations 是否排除JDK自带注解(java、javax包下的注解) * @return 存在符合要求的注解返回true,否则返回false */ public static boolean isClassAnnotated(Class<?> targetClass, String scanPackage, boolean excludeJdkAnnotations) { // 关闭默认过滤器,支持扫描所有类而非仅Spring组件 ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false); // 添加自定义注解匹配规则 scanner.addIncludeFilter(new TypeFilter() { @Override public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException { AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata(); Set<String> annotationTypes = annotationMetadata.getAnnotationTypes(); // 类上没有任何注解直接返回不匹配 if (annotationTypes.isEmpty()) { return false; } // 开启JDK注解过滤的场景下,过滤掉java、javax开头的原生注解 if (excludeJdkAnnotations) { return annotationTypes.stream().noneMatch(anno -> anno.startsWith("java.") || anno.startsWith("javax.")); } return true; } }); // 扫描指定包,拿到所有符合条件的类全限定名集合 Set<String> annotatedClassNames = scanner.findCandidateComponents(scanPackage) .stream() .map(BeanDefinition::getBeanClassName) .collect(Collectors.toSet()); return annotatedClassNames.contains(targetClass.getName()); } }
使用示例
// 示例:扫描com.example包下所有类,判断UserService类是否被非JDK的任意注解修饰 boolean hasAnnotation = AnnotationCheckUtils.isClassAnnotated(UserService.class, "com.example", true);
注意事项
- 当前实现默认覆盖所有编译时、运行时注解,如果仅需要校验运行时可见的注解,可以在过滤逻辑中额外加
@Retention(RetentionPolicy.RUNTIME)的判断 - 扫描器原生支持通配符包路径、多包路径逗号分隔的配置,可根据业务需求调整扫描范围
- 依赖全部来自Spring核心包,无需额外引入第三方依赖,适配所有SpringBoot、普通Spring项目
内容的提问来源于stack exchange,提问作者vshved
相关产品推荐
相关产品推荐

