通过指定一个包名获取该包名下所有的类,主要思路是遍历当前jvm依赖的jar包,以及引用的class文件目录,即java.class.path,在java中,我们可以使用System.getProperty获取其值,具体实现为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| private List<Class<?>> getClassByPackageName(String packageName) { List<Class<?>> classes = new ArrayList<>(); String packagePath = packageName.replace(".", "/"); String[] classPathEntries = System.getProperty("java.class.path") .split(System.getProperty("path.separator")); for (String classpathEntry : classPathEntries) { if (classpathEntry.endsWith(".jar")) { File jar = new File(classpathEntry); try (FileInputStream fileInputStream = new FileInputStream(jar); JarInputStream jarInputStream = new JarInputStream(fileInputStream)) { JarEntry entry; while ((entry = jarInputStream.getNextJarEntry()) != null) { String name = entry.getName(); if (name.endsWith(".class")) { if (name.contains(packagePath) && name.endsWith(".class")) { String classPath = name.substring(0, entry.getName().length() - 6); classPath = classPath.replaceAll("[|/]", "."); classes.add(Class.forName(classPath)); } } } } catch (Exception e) { throw new RuntimeException(e); } } else { try { File base = new File(classpathEntry + File.separatorChar + packagePath); Queue<File> fileQueue = new LinkedList<>(); fileQueue.offer(base); while (fileQueue.peek() != null) { File currentFile = fileQueue.poll(); if (currentFile.isDirectory()) { File[] subFiles = currentFile.listFiles(); if (subFiles != null) { for (File subFile : subFiles) { fileQueue.offer(subFile); } } } else if (currentFile.isFile()) { if (currentFile.getName().endsWith(".class")) { String className = currentFile.getPath() .replace(classpathEntry + "/", "") .replace("/", "."); className = className.substring(0, className.length() - 6); classes.add(Class.forName(className)); } } } } catch (Exception e) { throw new RuntimeException(e); } } } return classes; }
|
如果你的项目引用了spring依赖包,那么也可以使用ClassPathScanningCandidateComponentProvider 获取包名下的class。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| private List<Class<?>> getClassByPackageName(String packageName) { List<Class<?>> clazzs = new ArrayList<>(); ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false); provider.addIncludeFilter((metadataReader, metadataReaderFactory) -> {
String className = metadataReader.getClassMetadata().getClassName(); try { Class<?> clazz = Class.forName(className); clazzs.add(clazz); } catch (ClassNotFoundException e) { throw new BizCoreException(e.getMessage()); }
return true; }); provider.findCandidateComponents(packageName); return clazzs; }
|