zoukankan      html  css  js  c++  java
  • JAVA 扫描指定路径下所有的jar包,并保存所有实现固定接口的类型

     private static Map<String, Object> loadAllJarFromAbsolute(String directoryPath) throws
                NoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
    
            File directory = new File(directoryPath);
            // 判断是否为文件夹,如果是文件,直接用单个jar解析的方法去解析
            if (!directory.isDirectory()) {
                // 添加jar扫描路径
                addUrl(directory);
                return loadJarFromAbsolute(directoryPath);
            }
            // 如果是文件夹,则需要循环加载当前文件夹下面的所有jar
            Map<String, Object> clazzMap = new HashMap<>(16);
            File[] jars = directory.listFiles();
            if (jars != null && jars.length > 0) {
                List<String> jarPath = new LinkedList<>();
                for (File file : jars) {
                    String fPath = file.getPath();
                    // 只加载jar
                    if (fPath.endsWith(".jar")) {
                        addUrl(file);
                        jarPath.add(fPath);
                    }
                }
                if (jarPath.size() > 0) {
                    for (String path : jarPath) {
                        clazzMap.putAll(loadJarFromAbsolute(path));
                    }
                }
            }
            return clazzMap;
        }
    
        private static Map<String, Object> loadJarFromAbsolute(String path) throws IOException {
            JarFile jar = new JarFile(path);
            Enumeration<JarEntry> entryEnumeration = jar.entries();
            Map<String, Object> clazzMap = new HashMap<>(32);
            while (entryEnumeration.hasMoreElements()) {
                JarEntry entry = entryEnumeration.nextElement();
                // 先获取类的名称,符合条件之后再做处理,避免处理不符合条件的类
                String clazzName = entry.getName();
                if (clazzName.endsWith(".class")) {
                    // 去掉文件名的后缀
                    clazzName = clazzName.substring(0, clazzName.length() - 6);
                    // 替换分隔符
                    clazzName = clazzName.replace("/", ".");
                    // 加载类,如果失败直接跳过
                    try {
                        Class<?> clazz = Class.forName(clazzName);
                        Class superClass = clazz.getSuperclass();
                        if (superClass.equals(ComponentExtend.class)) {
                            Object o = clazz.newInstance();
                            Method fieldExtendComponentId = clazz.getMethod("extendComponentId");
                            String id = (String) fieldExtendComponentId.invoke(o);
                            clazzMap.put(id, o);
                        }
                    } catch (Throwable e) {
                        // 这里可能出现有些类是依赖不全的,直接跳过,不做处理,也没法做处理
                    }
                }
            }
            return clazzMap;
        }
    
        private static void addUrl(File jarPath) throws NoSuchMethodException, InvocationTargetException,
                IllegalAccessException, MalformedURLException {
    
            URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
            Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
            if (!method.isAccessible()) {
                method.setAccessible(true);
            }
            URL url = jarPath.toURI().toURL();
            // 把当前jar的路径加入到类加载器需要扫描的路径
            method.invoke(classLoader, url);
        }
  • 相关阅读:
    BUAA2020软工作业(三)——个人项目
    BUAA2020软工作业(二)——对软件工程的初步理解
    BUAA2020软工作业(一)——谈谈我和计算机的缘分
    OO第四单元总结与课程总结
    OO第三单元总结——JML
    面向对象第二单元总结——魔鬼电梯
    面向对象设计与构造——第一单元总结
    提问回顾与个人总结
    【技术博客】Flutter—使用网络请求的页面搭建流程、State生命周期、一些组件的应用
    软件案例分析
  • 原文地址:https://www.cnblogs.com/zzq-include/p/12061113.html
Copyright © 2011-2022 走看看