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);
        }
  • 相关阅读:
    前天去游泳了
    Microsoft今天开了中文的MSDN了,以后查资料有时要快了点吧
    Visual Studio .NET已检测到指定的WEB服务运行的不是ASP.NET 1.1版
    sqlserver 2005 利用游标解决标量值函数主键自增id批量导入数据问题
    nvarchar查询条件中不用加单引号''吗?
    使用标量值函数作为主键自增值的时候,动软代码生成器的插入方法需要去掉主键的参数。
    c#里的'0','1'对应sqlserver2005中的False,True
    三元运算符绑定缩略内容
    循环插入数据存储过程
    01|02|03| ====> (01,02,03)用于in id数组这种查询方式
  • 原文地址:https://www.cnblogs.com/zzq-include/p/12061113.html
Copyright © 2011-2022 走看看