經過形如:com.xxx.yyy.zzz形式的包名,加載包下全部的類java
package com.chuyutech.rssp.openservice.service.data; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; /** * @description: 簡單的文件操做類,包含一些文件的基本操做 * * @author cwh * */ public class FileOpreation { /** * 根據包名訪問磁盤文件 * * @param packageName:形如com.xxx.yyy.zzz以點號分割 */ public static Set<Class<?>> getClazz(String packageName) { // 是否遞歸 boolean isRecursion = true; // 定義變量,保存class文件 Set<Class<?>> clazz = new LinkedHashSet<Class<?>>(); char dot = '.'; char sprit = '/'; try { // 根據當前線程獲取ContextClassLoader類加載器 需注意:分隔符的轉換 // getResources方法定義的資源是 '/' 分隔符 Enumeration<URL> resources = Thread.currentThread().getContextClassLoader() .getResources(packageName.replace(dot, sprit)); // 遍歷枚舉 while (resources.hasMoreElements()) { URL url = resources.nextElement(); // url:file:/E:/03.WorkSpaceToNew/soldier-openservice/target/classes/com/chuyutech/rssp/openservice/common/db/dao System.out.println("url:" + url.toString()); // 獲取協議名稱 String protocol = url.getProtocol(); // 若是爲文件類型 接下來就是File類的操做 if (protocol.equals("file")) { // 使用特定的編碼方案解碼url String packagePath = URLDecoder.decode(url.getFile(), "UTF-8"); // 調用方法遞歸獲取文件 getClazzFromPath(packageName, packagePath, isRecursion, clazz); } } } catch (IOException e) { e.printStackTrace(); } return clazz; } /** * 獲取文件中class文件 * * @param packageName:包名; * packagePath:文件路徑;isRecursion:是否遞歸 */ public static void getClazzFromPath(String packageName, String packagePath, boolean isRecursion, Set<Class<?>> clazz) { char dot = '.'; // 根據路徑名獲取File文件對象 File file = new File(packagePath); if (!file.exists() || !file.isDirectory()) { return; } // 以File數組的形式列出全部的文件 File[] files = file.listFiles(new FileFilter() { // 匿名內部類重寫FIleFilter @Override public boolean accept(File pathName) { // 自定義過濾規則 若是能夠循環(包含子目錄) 或者是以.class結尾的文件(編譯好的java類文件) return ((isRecursion && pathName.isDirectory()) || pathName.getName().endsWith(".class")); } }); // 遍歷files for (File destFile : files) { // 若是是目錄 則繼續掃描 if (destFile.isDirectory()) { getClazzFromPath(packageName + dot + destFile.getName(), destFile.getAbsolutePath(), isRecursion, clazz); } else { // 若是是編譯後java類文件 去掉後面的.class 只留下類名 String fileName = destFile.getName().substring(0, destFile.getName().lastIndexOf(dot)); // 添加到集合中去 經過完整包名+"."+文件名 加載class try { // Class<?> forName = Class.forName(packageName + dot + // className); 此方法在會初始化所加載類的static靜態代碼塊 Class<?> loadClass = Thread.currentThread().getContextClassLoader() .loadClass(packageName + dot + fileName); clazz.add(loadClass); } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } public static void main(String[] args) { String packageName = "com.chuyutech.rssp.openservice.common.db.dao"; Set<Class<?>> clazz = getClazz(packageName); System.out.println(clazz.size()); for (Class<?> class1 : clazz) { System.out.println(class1.getName()); } } }
3.1:實現的大體邏輯:數組
根據當前線程獲取ContextClassLoader類加載器 ,經過類加載器的getResources(String name)方法獲取包名所對應的URL.ide
經過URL獲取絕對路徑,使用File類的 java.io.listFiles(FileFilter filter)列出全部的文件或目錄編碼
對上一步獲取的文件或目錄遞歸調用,最後經過Thread.currentThread().getContextClassLoader()
.loadClass(className)獲取到Class對象保存到set集合中.url
3.2:注意:分隔符的轉換:getResources方法定義的資源是 '/' 分隔符spa
---------------------over-----------------------.net