Spring 原始碼閱讀 01:Resource 資源抽象
攜手創作,共同成長!這是我參與「掘金日新計劃 · 8 月更文挑戰」的第18天,點選檢視活動詳情
在 Spring 的核心原始碼中,Resource
介面定義了 Spring 對底層資源訪問的抽象,通過實現 Resource 介面,我們可以開發各種資源的訪問能力。以 Spring 自身為例,Resource
的使用非常廣泛,我們可以在原始碼中的很多方法或者構造方法中看到 Resource
型別的引數。比如,通過 XML 載入容器配置、從 application.properties 檔案讀取 Spring Boot 專案配置資訊,都是通過 Resource 介面的實現類來實現對這些檔案的訪問的。
Resource
介面
Resource
介面的定義如下:
public interface Resource extends InputStreamSource {
boolean exists();
boolean isReadable();
boolean isOpen();
boolean isFile();
URL getURL() throws IOException;
URI getURI() throws IOException;
File getFile() throws IOException;
ReadableByteChannel readableChannel() throws IOException;
long contentLength() throws IOException;
long lastModified() throws IOException;
Resource createRelative(String relativePath) throws IOException;
String getFilename();
String getDescription();
}
在以上的方法中:
exist()
和isXXX()
方法提供了對資源狀態的判斷;getFile()
、getURI()
和getURL()
提供了資源到File
、URI
、URL
的轉換;getFilename()
、getDescription()
提供了一些資源資訊的獲取,一般用於日誌資訊。
此外,它還繼承了 InputStreamSource
介面:
public interface InputStreamSource {
InputStream getInputStream() throws IOException;
}
這裡的 getInputStream()
提供了從資源獲取輸入流的方法,每次呼叫這個方法,都需要返回一個新的輸入流,不過要注意,輸入流不在被使用的時候,一定要記得關閉。
Resource
實現類
在 Spring 中,已經包含了很多 Resource
的實現類,如下是一些常見的 Resource
實現類:
從這些實現類的名稱中,我們就能看出它們分別實現了那些來源的資源訪問。下面我們分別分析一下這幾個實現類:
FileSystemResource
一個 FileSystemResource
可以通過 File 物件或者檔案路徑來建立,在 FileSystemResource
類中,有以下三個成員變數:
``` private final String path;
@Nullable private final File file;
private final Path filePath; ```
它們會在構造方法中被初始化,值分別是檔案路徑字串、訪問檔案的 File
物件、檔案路徑對應的 Path
物件。
當呼叫 getInputStream()
方法的時候,會通過 File 物件建立一個 InputStream
物件。其他的一些操作也都會在 File 物件上完成。
ByteArrayResource
從 ByteArrayResource
的名字就可以看出,建立它並不需要外部資源,只需要提供一個 ByteArray
即可。在 ByteArrayResource
中只有兩個成員變數:
``` private final byte[] byteArray;
private final String description; ```
分別代表 byteArray 本身和其描述資訊,我們可以在建立物件時給它提供一個描述,如果不提供,預設的描述資訊是 resource loaded from byte array
,當需要呼叫 getInputStream()
獲取輸入流的時候,將會得到一個 ByteArrayInputStream
。實現方法如下:
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(this.byteArray);
}
ByteArrayResource
比較適用於一些需要用 ByteArray
建立一次性輸入流的地方。
UrlResource
UrlResource
可以使用 URL
建立,也可以使用 URI
建立,可以用來訪問一些需要通過 HTTP 或者 FTP 等訪問的檔案和內容。
當呼叫 getInputStream()
方法獲取資料流的時候,會通過 URL
建立 URLConnection
,然後從中獲取 InputStream
物件,程式碼如下:
@Override
public InputStream getInputStream() throws IOException {
URLConnection con = this.url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
try {
return con.getInputStream();
}
catch (IOException ex) {
// Close the HTTP connection (if applicable).
if (con instanceof HttpURLConnection) {
((HttpURLConnection) con).disconnect();
}
throw ex;
}
}
ClassPathResource
ClassPathResource
提供了從類路徑訪問資源的方法,建立 ClassPathResource
需要提供一個資源路徑,以及一個類載入器或者一個類物件。我們通常在 Spring 的配置檔案中使用 classpath:
作為字首的資源路徑,都是通過 ClassPathResource
讀取的。
InputStreamResource
我們也可以使用 InputStreamResource
將一個已經建立的 InputStream
封裝成一個 Resource
,當通過 getInputStream()
獲取輸入流的時候,會得到我們建立 InputStreamResource
時提供的 InputStream
。當沒有其他的 Resource
實現類可以適用當前資源的時候,可以使用它,不過,這個資源的資料流只能被讀取一次。
- Spring 原始碼閱讀 42:AutowiredAnnotationBeanPostProcessor 分析(3)
- Spring 原始碼閱讀 41:AutowiredAnnotationBeanPostProcessor 分析(2)
- Kafka 消費者組 Rebalance 詳細過程
- Spring 原始碼閱讀 01:Resource 資源抽象
- 初識機器學習:迴歸分析
- 初識機器學習:Louvain 社群發現演算法
- 初識機器學習:關聯規則
- 使用 Redis 實現分散式鎖的方法
- Kafka 目錄裡的指令碼那麼多,它們都是用來幹什麼的?
- Kafka 消費者組位移重設的幾種方式
- LeetCode - 84. 柱狀圖中最大的矩形
- LeetCode - 22. 括號生成