private static Map loadAllJarFromAbsolute(String directoryPath) throwsNoSuchMethodException, InvocationTargetException, IllegalAccessException, IOException {
File directory= newFile(directoryPath);//判断是否为文件夹,如果是文件,直接用单个jar解析的方法去解析
if (!directory.isDirectory()) {//添加jar扫描路径
addUrl(directory);returnloadJarFromAbsolute(directoryPath);
}//如果是文件夹,则需要循环加载当前文件夹下面的所有jar
Map clazzMap = new HashMap<>(16);
File[] jars=directory.listFiles();if (jars != null && jars.length > 0) {
List 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));
}
}
}returnclazzMap;
}private static Map loadJarFromAbsolute(String path) throwsIOException {
JarFile jar= newJarFile(path);
Enumeration entryEnumeration =jar.entries();
Map 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) {//这里可能出现有些类是依赖不全的,直接跳过,不做处理,也没法做处理
}
}
}returnclazzMap;
}private static void addUrl(File jarPath) throwsNoSuchMethodException, 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);
}