Java獲取包或jar下面的所有class檔案
阿新 • • 發佈:2019-02-05
import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.net.URLDecoder; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class ClassHelper { /** * 從包package中獲取所有的Class * * @param pkg * @return */ public static Set<Class<?>> getClzFromPkg(String pkg) { //第一個class類的集合 Set<Class<?>> classes = new LinkedHashSet<>(); // 獲取包的名字 並進行替換 String pkgDirName = pkg.replace('.', '/'); try { Enumeration<URL> urls = ClassHelper.class.getClassLoader().getResources(pkgDirName); while (urls.hasMoreElements()) { URL url = urls.nextElement(); // 得到協議的名稱 String protocol = url.getProtocol(); // 如果是以檔案的形式儲存在伺服器上 if ("file".equals(protocol)) { // 獲取包的物理路徑 String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); // 以檔案的方式掃描整個包下的檔案 並新增到集合中 findClassesByFile(pkg, filePath, classes); } else if ("jar".equals(protocol)) { // 如果是jar包檔案 // 獲取jar JarFile jar = ((JarURLConnection) url.openConnection()).getJarFile(); //掃描jar包檔案 並新增到集合中 findClassesByJar(pkg, jar, classes); } } } catch (IOException e) { e.printStackTrace(); } return classes; } private static void findClassesByFile(String pkgName, String pkgPath, Set<Class<?>> classes) { // 獲取此包的目錄 建立一個File File dir = new File(pkgPath); // 如果不存在或者 也不是目錄就直接返回 if (!dir.exists() || !dir.isDirectory()) { return; } // 如果存在 就獲取包下的所有檔案 包括目錄 // File[] dirfiles = dir.listFiles(new FileFilter() { // // 自定義過濾規則 如果可以迴圈(包含子目錄) 或則是以.class結尾的檔案(編譯好的java類檔案) // public boolean accept(File file) { // return file.isDirectory()|| file.getName().endsWith(".class"); // } // }); File[] dirfiles = dir.listFiles(pathname -> pathname.isDirectory() || pathname.getName().endsWith("class")); if (dirfiles == null || dirfiles.length == 0) { return; } String className; Class clz; // 迴圈所有檔案 for (File f : dirfiles) { // 如果是目錄 則繼續掃描 if (f.isDirectory()) { findClassesByFile(pkgName + "." + f.getName(),pkgPath + "/" + f.getName(),classes); continue; } // 如果是java類檔案 去掉後面的.class 只留下類名 className = f.getName(); className = className.substring(0, className.length() - 6); //載入類 clz = loadClass(pkgName + "." + className); // 新增到集合中去 if (clz != null) { classes.add(clz); } } } private static void findClassesByJar(String pkgName, JarFile jar, Set<Class<?>> classes) { String pkgDir = pkgName.replace(".", "/"); // 從此jar包 得到一個列舉類 Enumeration<JarEntry> entry = jar.entries(); JarEntry jarEntry; String name, className; Class<?> claze; // 同樣的進行迴圈迭代 while (entry.hasMoreElements()) { // 獲取jar裡的一個實體 可以是目錄 和一些jar包裡的其他檔案 如META-INF等文 jarEntry = entry.nextElement(); name = jarEntry.getName(); // 如果是以/開頭的 if (name.charAt(0) == '/') { // 獲取後面的字串 name = name.substring(1); } if (jarEntry.isDirectory() || !name.startsWith(pkgDir) || !name.endsWith(".class")) { continue; } //如果是一個.class檔案 而且不是目錄 // 去掉後面的".class" 獲取真正的類名 className = name.substring(0, name.length() - 6); //載入類 claze = loadClass(className.replace("/", ".")); // 新增到集合中去 if (claze != null) { classes.add(claze); } } } /** * 載入類 * @param fullClzName 類全名 * @return */ private static Class<?> loadClass(String fullClzName) { try { return Thread.currentThread().getContextClassLoader().loadClass(fullClzName); } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } }
參考連結: