package com.lms.common.util;import java.io.File;import java.io.IOException;import java.net.JarURLConnection;import java.net.URL;import java.nio.file.*;import java.nio.file.attribute.BasicFileAttributes;import java.util.Enumeration;import java.util.HashMap;import java.util.Map;import java.util.function.Predicate;import java.util.jar.JarEntry;import java.util.jar.JarFile;/** * @Author: 李孟帅 * @Date: 2021-12-30 15:04 * @Description: */public class ClassScanner { Map<String, Class<?>> classMap = new HashMap<>(); Predicate<String> packagePredicate; Predicate<Class<?>> classPredicate; public ClassScanner() { } public ClassScanner(Predicate<String> packagePredicate) { this.packagePredicate = packagePredicate; } public ClassScanner(Predicate<String> packagePredicate, Predicate<Class<?>> classPredicate) { this.packagePredicate = packagePredicate; this.classPredicate = classPredicate; } public Map<String, Class<?>> scanAll() throws Exception { String javaClassPath = System.getProperty("java.class.path"); String[] classPaths = javaClassPath.split(";"); for (String classPath : classPaths) { // jar包 if (classPath.endsWith(".jar")) { scanClassesByJar(classPath); } else { //路径 scanClassesByPath(classPath); } } return classMap; } // 加载路径下的class文件 private void scanClassesByPath(String classPath) { File file = new File(classPath); if (!file.exists()) { return; } try { if (file.isDirectory() || classPath.endsWith(".class")) { Files.walkFileTree(Paths.get(classPath), new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { try { if (file.toString().endsWith(".class")) { String name = file.toString().replace(classPath + File.separator, ""); // 过滤包 name = name.replace(File.separatorChar + "", "."); if (matchPackageName(name)) { String className = name.substring(0, name.length() - 6); Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass(className); // 过滤类 if (matchClass(cls)) { classMap.put(className, cls); } } } } catch (Throwable e) { e.printStackTrace(); } return super.visitFile(file, attrs); } }); } } catch (IOException e) { e.printStackTrace(); } } // 加载所有的jar包内的class文件 private void scanClassesByJar(String classPath) throws IOException { String file = "file:/" + classPath.replace("\\", "/") + "!/"; URL url = new URL("jar", "", file); JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); JarFile jarFile = jarURLConnection.getJarFile(); Enumeration<JarEntry> entries = jarFile.entries(); while (entries.hasMoreElements()) { JarEntry jarEntry = entries.nextElement(); String name = jarEntry.getName(); // 过滤包 if (!matchPackageName(name.replace("/", "."))) { continue; } // class文件 if (!jarEntry.isDirectory() && name.endsWith(".class")) { try { String className = name.substring(0, name.length() - 6).replace("/", "."); Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass(className); // 过滤类 if (matchClass(cls)) { classMap.put(className, cls); } } catch (Throwable e) { e.printStackTrace(); } } } } // 过滤包 private boolean matchPackageName(String name) { return packagePredicate == null || packagePredicate.test(name.replace("/", ".")); } // 过滤类 private boolean matchClass(Class<?> cls) { return classPredicate == null || classPredicate.test(cls); } public static void main(String[] args) throws Exception { // ClassScanner classScanner = new ClassScanner(p -> p.startsWith("java.lang")); ClassScanner classScanner = new ClassScanner(p -> p.startsWith("com.lms"), cls -> { return Object.class.isAssignableFrom(cls); }); Map<String, Class<?>> classMap = classScanner.scanAll(); classMap.forEach((k, v) -> System.out.println(k + " -- " + v)); }}
使用
public static void main(String[] args) throws Exception { // ClassScanner classScanner = new ClassScanner(p -> p.startsWith("java.lang")); ClassScanner classScanner = new ClassScanner(p -> p.startsWith("") , cls -> BasicLookAndFeel.class.isAssignableFrom(cls) && !Modifier.isAbstract(cls.getModifiers())); Map<String, Class<?>> classMap = classScanner.scanAll(); classMap.forEach((k, v) -> System.out.println(k + " -- " + v)); }