抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

通过指定一个包名获取该包名下所有的类,主要思路是遍历当前jvm依赖的jar包,以及引用的class文件目录,即java.class.path,在java中,我们可以使用System.getProperty获取其值,具体实现为:

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。

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;
}

评论