1. 程式人生 > >Java工具包:資源訪問器

Java工具包:資源訪問器

Java *.class 編譯檔案構成了 Java 程式,而 Java 程式則通過 classpath 能夠訪問到 class 檔案。一個 Java 程式,classpath 位置可以不止一個,而儲存 class 的介質也不止一種,磁碟檔案系統,jar 包甚至 zip 包這些介質都可以讓 Java 程式讀取,classpath 只是 JVM 對於其程式抽象的一個檔案訪問系統罷了。每個位置都可以用 URL 來描述,不同的位置之間用分號分隔。

特別地,JVM 程式能訪問的不僅僅是 *.class,還可以是非 class 檔案,於是我們可以稱其“資原始檔”。同樣,他們可以在目錄,或者打包到 jar 包裡面中,只要定義為 classpath 可以訪問的位置即可。

AbstractScanner 資源掃描器

掃描器的原理不復雜,首先是對輸入的 Java 包名例如 com.foo.bar 轉為 URL 物件。
在這裡插入圖片描述
然後得到 URL 集合的 Enumeration 列舉型別,——因為包名下面可能多個目錄的。最終如上述所見,分別對 file、jar、zip 得到的資源進行處理,交由子類的覆寫方法決定是否需要這些的資源。具體怎麼判斷是否需要該資源我們下面再講。

查詢過程是遞迴的,也就是說可以對所有子目錄進行搜尋。

AbstractScanner 是一個抽象類,泛型 T 是欲查詢的目標型別。符合條件的資源儲存在一個 set 之中。LinkedHashSet 是 Set 集合的一個實現,具有 set 集合不重複的特點,具有可插入的順序的特定,比較適合當前結果資料容器之場景。

條件過濾

掃描器可以掃描任何儲存在 classpath 的東西,當然一般情況下我們都是有特定範圍的查詢。於是 fileFilter 就被派上用場了。
抽象類 AbstractScanner 抽象以下三個方法,
在這裡插入圖片描述
怎麼給出實現呢?這裡以 ScanClass 為例子,說明查詢只是 *.class 編譯檔案。
在這裡插入圖片描述
這樣就收集了 class 的路徑。注意只是 String 型別的資源路徑。而 AbstractScanner 這裡期待的型別是 Class,於是就有一個 path 轉換為 Class 型別的過程,由實現方法 onFileAdding/onJarAdding 完成。
在這裡插入圖片描述

查詢任意型別

前面例子是 Class,且有特定的 Java 給泛型 T 所使用——如果查詢的資源是 *.txt 檔案,能否呢?答案是肯定,這時我們把 T 宣告為 Object,然後 FileFilter 改為判斷 txt 字尾即可。下面是完整的實現。
在這裡插入圖片描述

查詢特定的類

前面我們提到有 ScannClass,用得比較多的是其靜態方法:
在這裡插入圖片描述
可見 Object 作為泛型引數就可以表示不同型別的 class。現在我們縮窄下範圍,只要求 IController 型別的 Class。
在這裡插入圖片描述
通過 class 的 isAssignableFrom() 方法可得知該類是否實現了 class 介面。