1. package com.lms.common.util;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.net.JarURLConnection;
  5. import java.net.URL;
  6. import java.nio.file.*;
  7. import java.nio.file.attribute.BasicFileAttributes;
  8. import java.util.Enumeration;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. import java.util.function.Predicate;
  12. import java.util.jar.JarEntry;
  13. import java.util.jar.JarFile;
  14. /**
  15. * @Author: 李孟帅
  16. * @Date: 2021-12-30 15:04
  17. * @Description:
  18. */
  19. public class ClassScanner {
  20. Map<String, Class<?>> classMap = new HashMap<>();
  21. Predicate<String> packagePredicate;
  22. Predicate<Class<?>> classPredicate;
  23. public ClassScanner() {
  24. }
  25. public ClassScanner(Predicate<String> packagePredicate) {
  26. this.packagePredicate = packagePredicate;
  27. }
  28. public ClassScanner(Predicate<String> packagePredicate, Predicate<Class<?>> classPredicate) {
  29. this.packagePredicate = packagePredicate;
  30. this.classPredicate = classPredicate;
  31. }
  32. public Map<String, Class<?>> scanAll() throws Exception {
  33. String javaClassPath = System.getProperty("java.class.path");
  34. String[] classPaths = javaClassPath.split(";");
  35. for (String classPath : classPaths) {
  36. // jar包
  37. if (classPath.endsWith(".jar")) {
  38. scanClassesByJar(classPath);
  39. } else { //路径
  40. scanClassesByPath(classPath);
  41. }
  42. }
  43. return classMap;
  44. }
  45. // 加载路径下的class文件
  46. private void scanClassesByPath(String classPath) {
  47. File file = new File(classPath);
  48. if (!file.exists()) {
  49. return;
  50. }
  51. try {
  52. if (file.isDirectory() || classPath.endsWith(".class")) {
  53. Files.walkFileTree(Paths.get(classPath), new SimpleFileVisitor<Path>() {
  54. @Override
  55. public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
  56. try {
  57. if (file.toString().endsWith(".class")) {
  58. String name = file.toString().replace(classPath + File.separator, "");
  59. // 过滤包
  60. name = name.replace(File.separatorChar + "", ".");
  61. if (matchPackageName(name)) {
  62. String className = name.substring(0, name.length() - 6);
  63. Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass(className);
  64. // 过滤类
  65. if (matchClass(cls)) {
  66. classMap.put(className, cls);
  67. }
  68. }
  69. }
  70. } catch (Throwable e) {
  71. e.printStackTrace();
  72. }
  73. return super.visitFile(file, attrs);
  74. }
  75. });
  76. }
  77. } catch (IOException e) {
  78. e.printStackTrace();
  79. }
  80. }
  81. // 加载所有的jar包内的class文件
  82. private void scanClassesByJar(String classPath) throws IOException {
  83. String file = "file:/" + classPath.replace("\\", "/") + "!/";
  84. URL url = new URL("jar", "", file);
  85. JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
  86. JarFile jarFile = jarURLConnection.getJarFile();
  87. Enumeration<JarEntry> entries = jarFile.entries();
  88. while (entries.hasMoreElements()) {
  89. JarEntry jarEntry = entries.nextElement();
  90. String name = jarEntry.getName();
  91. // 过滤包
  92. if (!matchPackageName(name.replace("/", "."))) {
  93. continue;
  94. }
  95. // class文件
  96. if (!jarEntry.isDirectory() && name.endsWith(".class")) {
  97. try {
  98. String className = name.substring(0, name.length() - 6).replace("/", ".");
  99. Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass(className);
  100. // 过滤类
  101. if (matchClass(cls)) {
  102. classMap.put(className, cls);
  103. }
  104. } catch (Throwable e) {
  105. e.printStackTrace();
  106. }
  107. }
  108. }
  109. }
  110. // 过滤包
  111. private boolean matchPackageName(String name) {
  112. return packagePredicate == null || packagePredicate.test(name.replace("/", "."));
  113. }
  114. // 过滤类
  115. private boolean matchClass(Class<?> cls) {
  116. return classPredicate == null || classPredicate.test(cls);
  117. }
  118. public static void main(String[] args) throws Exception {
  119. // ClassScanner classScanner = new ClassScanner(p -> p.startsWith("java.lang"));
  120. ClassScanner classScanner = new ClassScanner(p -> p.startsWith("com.lms"), cls -> {
  121. return Object.class.isAssignableFrom(cls);
  122. });
  123. Map<String, Class<?>> classMap = classScanner.scanAll();
  124. classMap.forEach((k, v) -> System.out.println(k + " -- " + v));
  125. }
  126. }

使用

  1. public static void main(String[] args) throws Exception {
  2. // ClassScanner classScanner = new ClassScanner(p -> p.startsWith("java.lang"));
  3. ClassScanner classScanner = new ClassScanner(p -> p.startsWith("")
  4. , cls -> BasicLookAndFeel.class.isAssignableFrom(cls) && !Modifier.isAbstract(cls.getModifiers()));
  5. Map<String, Class<?>> classMap = classScanner.scanAll();
  6. classMap.forEach((k, v) -> System.out.println(k + " -- " + v));
  7. }