扫描一个类所在目录下的所有类的类名[包括Jar和非jar]

/**
     * 扫描一个类所在目录下的所有类的类名
     *
     * @param clazz  要扫描的基础类
     * @param filter 过滤器 为空的时候不过滤
     * @return 一个全路径类名的List
     */
    public static List scanAllClass(Class clazz, Function filter) {
        List classes = new LinkedList<>();
        try {
            URL url = clazz.getResource("");
            String decode = URLDecoder.decode(url.getPath(), "UTF-8");
            //判断是jar包还是文件夹
            String[] split = decode.split("\\.jar!/");
            if (split.length == 2) {

                //打开jar文件
                JarURLConnection connection = (JarURLConnection) url.openConnection();
                JarFile jarFile = connection.getJarFile();
                Enumeration jarEntries = jarFile.entries();
                //遍历jar包下的所有文件
                while (jarEntries.hasMoreElements()) {
                    JarEntry jarEntry = jarEntries.nextElement();
                    String jarEntryName = jarEntry.getName();
                    //查找出类
                    if (jarEntryName.startsWith(split[1]) && jarEntryName.endsWith(".class")) {
                        String className = jarEntryName.replace("/", ".");
                        //默认不包含内部类
                        if (filter != null && !filter.apply(className)) {
                            continue;
                        }
                        classes.add(className);
                    }
                }
            } else {
                //todo mac 下测试效果
                //计算出从包名开始往下的路径
                //linux 下和windows下有所区别  windows下的decode 前面会加上一个 / 所以分隔符是\的时候 subNum要+1
                String separator = System.getProperty("file.separator");
                int subNum = "\\".equals(separator) ? 2 : 1;
                int bathLength = decode.length() - subNum - clazz.getPackage().getName().length();
                //BFS
                Queue queue = new LinkedList<>();
                File file = new File(decode);
                queue.add(file);
                while (!queue.isEmpty()) {
                    for (int i = 0; i < queue.size(); i++) {
                        File poll = queue.poll();
                        String absolutePath = poll.getCanonicalPath();
                        if (absolutePath.endsWith(".class")) {
                            String substring = absolutePath.substring(bathLength);
                            String className = substring.replace(separator, ".");
                            //执行过滤器
                            if (filter != null && !filter.apply(className)) {
                                continue;
                            }
                            //将分割符切换成.
                            classes.add(className);
                        } else {
                            if (poll.canRead() && poll.isDirectory()) {
                                File[] files = poll.listFiles();
                                //如果有子文件 入队
                                for (File f : files) {
                                    queue.add(f);
                                }
                            }
                        }
                    }

                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return classes;
    }


    public static void main(String[] args) {

        System.out.println(scanAllClass(DataMemoryApplication.class, null));

        System.out.println(scanAllClass(org.springframework.cache.Cache.class, null));
        //过滤内部类
        System.out.println(scanAllClass(org.springframework.cache.Cache.class, s -> !s.contains("$")));
    }

 

你可能感兴趣的:(代码段)