【Java】包、jar包的掃描
阿新 • • 發佈:2018-12-13
package com.test.package_scanner.core; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.JarURLConnection; import java.net.URISyntaxException; import java.net.URL; import java.util.Enumeration; import java.util.jar.JarEntry; public abstract class PackageScanner { public PackageScanner() { } // scanPackage方法的過載 public void scanPackage(Class<?> klass) { scanPackage(klass.getPackage().getName()); } public void scanPackage(String packageName) { // 將包名稱轉換為路徑名稱的形式 String packagePath = packageName.replace(".", "/"); try { // 由類載入器得到URL的列舉 Enumeration<URL> resources = Thread.currentThread() .getContextClassLoader() .getResources(packagePath); while (resources.hasMoreElements()) { URL url = resources.nextElement(); // 處理jar包 if (url.getProtocol().equals("jar")) { parse(url); } else { File file = new File(url.toURI()); if (file.exists()) { // 處理普通包 parse(file, packageName); } } } } catch (IOException e) { e.printStackTrace(); } catch (URISyntaxException e) { e.printStackTrace(); } } // 抽象方法,由使用者自行處理掃描到的類 public abstract void dealClass(Class<?> klass); // jar包的掃描 private void parse(URL url) throws IOException { Enumeration<JarEntry> jarEntries = ((JarURLConnection) url.openConnection()) .getJarFile().entries(); while (jarEntries.hasMoreElements()) { JarEntry jarEntry = jarEntries.nextElement(); String jarName = jarEntry.getName(); if (!jarEntry.isDirectory() && jarName.endsWith(".class")) { // 將檔案路徑名轉換為包名稱的形式 dealClassName(jarName.replace("/", ".").replace(".class", "")); } } } // 普通包的掃描 private void parse(File curFile, String packageName) { File[] fileList = curFile.listFiles(new FileFilter() { // 篩選檔案和class檔案,其餘檔案不處理 @Override public boolean accept(File pathname) { return pathname.isDirectory() || pathname.getName().endsWith(".class"); } }); // 目錄就是一顆樹,對樹進行遞迴,找到class檔案 for (File file : fileList) { String fileName = file.getName(); if (file.isDirectory()) { parse(file, packageName + "." + fileName); } else { String className = packageName + "." + fileName.replace(".class", ""); dealClassName(className); } } } // 將找到的class檔案生成類物件 private void dealClassName(String className) { try { Class<?> klass = Class.forName(className); // 註解、介面、列舉、原始型別不做處理 if (!klass.isAnnotation() && !klass.isInterface() && !klass.isEnum() && !klass.isPrimitive()) { dealClass(klass); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } }
對如下目錄掃描
package com.test.package_scanner.demo; import com.test.package_scanner.core.PackageScanner; public class Demo { public static void main(String[] args) { new PackageScanner() { @Override public void dealClass(Class<?> klass) { System.out.println(klass); } }.scanPackage("com"); } }
結果如下 其中帶有$1的是匿名內部類