路徑掃描工具SearchClassUtil
,用于掃描指定包(XXXX)下的所有.class
文件,并將它們的全限定類名(如tomcat.SearchClassUtil
)收集到列表中返回。該工具使用遞歸文件遍歷和反射機制,是實現 Spring 框架組件掃描、Servlet 容器類加載等功能的基礎。
完整代碼:
package tomcat;import java.io.File;
import java.util.ArrayList;
import java.util.List;/*
* 掃描包下的文件,獲取全路徑名
* */
public class SearchClassUtil {public static List<String> classPaths = new ArrayList<String>();public static List<String> searchClass(){//需要掃描的包名String basePack = "tomcat";//將獲取到的包名轉換為路徑String classPath = SearchClassUtil.class.getResource("/").getPath();basePack = basePack.replace(".", File.separator);String searchPath = classPath + basePack;doPath(new File(searchPath),classPath);//這個時候我們已經得到了指定包下所有的類的絕對路徑了。我們現在利用這些絕對路徑和java的反射機制得到他們的類對象return classPaths;}/*** 該方法會得到所有的類,將類的絕對路徑寫入到classPaths中* @param file*/private static void doPath(File file,String classpath) {if (file.isDirectory()) {//文件夾//文件夾我們就遞歸File[] files = file.listFiles();for (File f1 : files) {doPath(f1,classpath);}} else {//標準文件//標準文件我們就判斷是否是class文件if (file.getName().endsWith(".class")) {String path = file.getPath().replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");//如果是class文件我們就放入我們的集合中。classPaths.add(path);}}}public static void main(String[] args) {List<String> classes = SearchClassUtil.searchClass();for (String s: classes) {System.out.println(s);}}
}
代碼逐行解釋
1. 類定義與成員變量
public class SearchClassUtil {public static List<String> classPaths = new ArrayList<String>();
}
- 功能:定義工具類,使用靜態列表存儲掃描到的類名。
- 注意點:靜態變量會在多次調用時累積結果,需手動清空或改進為非靜態設計。
2.?searchClass()
?方法
public static List<String> searchClass(){String basePack = "tomcat";String classPath = SearchClassUtil.class.getResource("/").getPath();basePack = basePack.replace(".", File.separator);String searchPath = classPath + basePack;doPath(new File(searchPath),classPath);return classPaths;
}
- 功能:入口方法,初始化掃描參數并啟動遞歸掃描。
- 步驟分解:
- 設置掃描包名:
basePack = "tomcat"
?硬編碼掃描目標包。 - 獲取類路徑根目錄:
?SearchClassUtil.class.getResource("/").getPath()
- 返回當前類所在的類路徑根(如
/target/classes/
或 JAR 包路徑)。 - 示例:若類位于
tomcat/SearchClassUtil.class
,則返回/path/to/classes/
。
- 返回當前類所在的類路徑根(如
- 轉換包名為路徑格式:
?basePack.replace(".", File.separator)
- 將包名(如
tomcat.util
)轉換為文件路徑(如tomcat/util
)。 - 使用
File.separator
確保跨平臺兼容性(Windows 為\
,Linux 為/
)。
- 將包名(如
- 拼接完整搜索路徑:
?String searchPath = classPath + basePack;
- 示例:拼接后為
/path/to/classes/tomcat/
。
- 示例:拼接后為
- 啟動遞歸掃描:
?doPath(new File(searchPath), classPath);
- 傳遞搜索目錄和類路徑根目錄。
- 設置掃描包名:
3.?doPath(File file, String classpath)
?方法
private static void doPath(File file, String classpath) {if (file.isDirectory()) {File[] files = file.listFiles();for (File f1 : files) {doPath(f1, classpath);}} else {if (file.getName().endsWith(".class")) {String path = file.getPath().replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");classPaths.add(path);}}
}
- 功能:遞歸遍歷文件系統,提取類名并存儲到列表。
- 邏輯分解:
- 目錄處理:
?if (file.isDirectory()) { ... }
- 遞歸調用
doPath
處理子文件 / 目錄。
- 遞歸調用
- 文件處理:
?if (file.getName().endsWith(".class")) { ... }
- 篩選
.class
文件。
- 篩選
- 路徑處理:
?String path = file.getPath().replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"").replace("\\",".").replace(".class","");
- 復雜替換邏輯詳解:
classpath.replace("/","\\").replaceFirst("\\\\","")
:- 將類路徑(如
/path/to/classes/
)轉換為系統路徑格式(如path\to\classes\
)。 - 示例:輸入
/C:/path/to/classes/
?→ 輸出C:\path\to\classes\
。
- 將類路徑(如
file.getPath().replace(...)
:- 移除類路徑前綴,保留相對路徑。
- 示例:原路徑
C:\path\to\classes\tomcat\MyClass.class
?→?tomcat\MyClass.class
。
replace("\\",".")
:- 將路徑分隔符轉換為
.
,形成類名格式。 - 示例:
tomcat\MyClass.class
?→?tomcat.MyClass.class
。
- 將路徑分隔符轉換為
replace(".class","")
:- 移除文件擴展名,得到全限定類名。
- 示例:
tomcat.MyClass.class
?→?tomcat.MyClass
。
- 復雜替換邏輯詳解:
- 目錄處理:
4.?main(String[] args)
?方法
public static void main(String[] args) {List<String> classes = SearchClassUtil.searchClass();for (String s: classes) {System.out.println(s);}
}
- 功能:測試工具類,打印掃描到的類名。
- 執行流程:
- 調用
searchClass()
方法獲取類名列表。 - 遍歷列表并打印每個類名。
- 調用
關鍵技術細節
1. 類路徑資源獲取
SearchClassUtil.class.getResource("/").getPath()
- 工作原理:
getResource("/")
返回類路徑根目錄的URL
對象。.getPath()
將URL
轉換為文件系統路徑。
- 注意點:
- 路徑格式可能包含協議前綴(如
file:/
),但后續替換邏輯會處理此問題。 - 在 JAR 包環境中,可能返回
jar:file:/path/to/app.jar!/
格式,此時該代碼會失效。
- 路徑格式可能包含協議前綴(如
2. 路徑處理邏輯
file.getPath().replace(classpath.replace("/","\\").replaceFirst("\\\\",""),"")
- 設計意圖:
- 移除類路徑前綴,保留相對路徑。
- 存在問題:
- 跨平臺兼容性:混用
/
和\\
作為路徑分隔符,可能在非 Windows 系統上出錯。 - 特殊路徑處理:若類路徑包含特殊字符(如空格),替換邏輯可能失效。
- 跨平臺兼容性:混用
3. 靜態列表的線程安全
public static List<String> classPaths = new ArrayList<String>();
4.classpath.replace("/","\\").replaceFirst("\\\\","")
?詳解
?這段代碼的核心目標是將類路徑字符串轉換為系統路徑格式,并移除可能存在的前導路徑分隔符,以便后續正確拼接和替換路徑。
?假設初始?classpath
?值為:
String classpath = "/C:/workspace/project/target/classes/";
-
第一步:
classpath.replace("/", "\\")
- 將所有斜杠?
/
?替換為反斜杠?\
- 結果:
"\C:\workspace\project\target\classes\"
- 將所有斜杠?
-
第二步:
.replaceFirst("\\\\", "")
- 使用正則表達式?
\\\\
(對應 Java 字符串中的?"\\"
,即正則中的?\
)匹配第一個反斜杠 - 將其替換為空字符串
- 結果:
"C:\workspace\project\target\classes\"
- 使用正則表達式?
5. dopath遞歸
假設目錄結構如下:
classes/
└── tomcat/├── util/│ ├── StringUtil.class│ └── FileUtil.class└── SearchClassUtil.class
遞歸執行步驟:
-
初始調用:
doPath("classes/tomcat/", "classes/")
- 處理目錄?
tomcat/
- 遞歸調用子項:
util/
?和?SearchClassUtil.class
- 處理目錄?
-
處理?
util/
?目錄:- 遞歸調用子項:
StringUtil.class
?和?FileUtil.class
- 遞歸調用子項:
-
處理?
StringUtil.class
:- 路徑轉換:
classes/tomcat/util/StringUtil.class
?→?tomcat.util.StringUtil
- 加入結果列表
- 路徑轉換:
-
處理?
FileUtil.class
:- 路徑轉換:
classes/tomcat/util/FileUtil.class
?→?tomcat.util.FileUtil
- 加入結果列表
- 路徑轉換:
-
返回處理?
SearchClassUtil.class
:- 路徑轉換:
classes/tomcat/SearchClassUtil.class
?→?tomcat.SearchClassUtil
- 加入結果列表
- 路徑轉換: