当前位置:   article > 正文

从接口/类上扫描注解的工具类_扫描注解工具类

扫描注解工具类
  1. package com.fastrpc.annotation;
  2. import com.fastrpc.extension.Holder;
  3. import lombok.extern.slf4j.Slf4j;
  4. import java.io.File;
  5. import java.io.FileFilter;
  6. import java.io.IOException;
  7. import java.lang.annotation.Annotation;
  8. import java.net.URL;
  9. import java.net.URLDecoder;
  10. import java.util.*;
  11. /**
  12. * @author: @zyz
  13. */
  14. @Slf4j
  15. public class ScannerUtils {
  16. /**
  17. * 缓存 key注解标记的所有接口
  18. */
  19. static final Map<Class<?>, Set<Class<?>>> cachedAnnotation=new HashMap<>();
  20. /**
  21. * 缓存所有已经扫描过的包 保存格式为 注解名&包名
  22. */
  23. static final Set<String> cachedDirName=new HashSet<>() ;
  24. /**
  25. * 标记遇到File时是否循环扫描
  26. */
  27. static final boolean recursive = true;
  28. /**
  29. * 加载注解标记过的类或接口
  30. * @param annotationClazz 指定需要获得的注解
  31. * @param dir dir为需要扫描的包名
  32. * @return
  33. */
  34. public static void loadClassOrInterface(Class<?> annotationClazz,String dir) {
  35. String name=annotationClazz.getSimpleName() + "&" + dir;
  36. if (cachedDirName.contains(name)) return;
  37. cachedDirName.add(name);
  38. String packageDirName = dir.replace('.', '/');
  39. Enumeration<URL> dirs;
  40. try {
  41. dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
  42. while (dirs.hasMoreElements()) {
  43. URL url = dirs.nextElement();
  44. String protocol = url.getProtocol();
  45. if ("file".equals(protocol)) {
  46. String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
  47. findAndAddClassesInPackageByFile(annotationClazz,dir, filePath);
  48. }
  49. }
  50. } catch (IOException e) {
  51. log.error("load annotation fail :" +e);
  52. cachedDirName.remove(name);
  53. throw new IllegalStateException(e);
  54. }
  55. }
  56. /**
  57. * 从文件下获去包下的所有Class
  58. * @param annotationClazz
  59. * @param packageName
  60. * @param packagePath
  61. */
  62. public static void findAndAddClassesInPackageByFile(Class<?> annotationClazz,String packageName,String packagePath)
  63. {
  64. File dir=new File(packagePath);
  65. if (!dir.exists()||!dir.isDirectory())
  66. {
  67. log.error("path does not exist :"+packagePath);
  68. throw new IllegalArgumentException("path does not exist :"+packagePath);
  69. }
  70. File[] dirFiles=dir.listFiles( file-> (recursive&&file.isDirectory())|| (file.getName().endsWith(".class")));
  71. try {
  72. Set<Class<?>> cachedSet=new HashSet<>();
  73. for (File file:dirFiles)
  74. {
  75. if (file.isDirectory())
  76. {
  77. findAndAddClassesInPackageByFile(annotationClazz,packageName+"."+file.getName(),file.getAbsolutePath());
  78. }else{
  79. // 若为.class文件
  80. String className=file.getName().substring(0,file.getName().length()-6);
  81. Class<?> clazz=Thread.currentThread().getContextClassLoader().loadClass(packageName+"."+className);
  82. if (clazz.isAnnotationPresent((Class<? extends Annotation>) annotationClazz))
  83. {
  84. cachedSet.add(clazz);
  85. }
  86. }
  87. }
  88. Set<Class<?>> classes = cachedAnnotation.computeIfAbsent(annotationClazz, aClass -> new HashSet<Class<?>>());
  89. classes.addAll(cachedSet);
  90. cachedAnnotation.put(annotationClazz,classes);
  91. } catch (ClassNotFoundException e) {
  92. log.error(e.getMessage());
  93. throw new IllegalArgumentException("The Class file could not be found ",e);
  94. }
  95. }
  96. /**
  97. * 获取所有标记annotationClazz注解的类或接口
  98. * @param annotationClazz
  99. * @param packageName
  100. * @return
  101. */
  102. public static Set<Class<?>> getClass(Class<?> annotationClazz,String packageName)
  103. {
  104. if (!cachedDirName.contains(annotationClazz.getName()+"&"+packageName))
  105. loadClassOrInterface(annotationClazz,packageName);
  106. return cachedAnnotation.get(annotationClazz);
  107. }
  108. /**
  109. * 若提前加载过就无需指定扫描包的路径
  110. * @param annotationClazz
  111. * @return
  112. */
  113. public static Set<Class<?>> getClass(Class<?> annotationClazz)
  114. {
  115. return cachedAnnotation.get(annotationClazz);
  116. }
  117. public static void main(String[] args) {
  118. Set<Class<?>> aClass = getClass(Controller.class, "com.fastrpc.service");
  119. if (aClass!=null)
  120. for (Class<?> cl:aClass) {
  121. System.out.println(cl.getName());
  122. }
  123. }
  124. }

 改写自:

Java中利用反射查找使用指定注解的类---找到指定包下的指定注解类_逝者如风-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/240374
推荐阅读
相关标签
  

闽ICP备14008679号