Spring源碼(4)-Spring中的Resource,ResourceLoader,容器的關係

之前提到Spring會將配置問價或者配置類讀取到內存轉換成一個個的Resource實例。然後將Resource解析一個個的BeanDefinitioon.

Resource接口

public interface Resource extends InputStreamSource 

Resource繼承於InputStreamSource接口 ,InputStreamSource接口僅僅定義了一個方法,獲取輸入流。Resource定義了對資源的基本操作。判斷資源是否存在,是否可讀,是否打開 ==。
在這裏插入圖片描述
Resource接口體系在這裏插入圖片描述

EncodedResource類

在這裏插入圖片描述
EncodedResource實現了了InputStreamSource接口,該類的主要作用是 對資源文件的編碼處理。

AbstractResource

在這裏插入圖片描述
該抽象類實現了大量的對Resource方法的默認公共實現。如果要實現自己的Resource,應該繼承該類,而不是實現頂層接口。

ClassPathResource類

提供根據類文件夾訪相對路徑問資源的能力。

FileSystemResource類

提供訪問系統資源的能力,但是JDK自帶的 File類相關,也不錯。
此外,FileSystemResource實現了WritableResource接口,WritableResource接口定義了 對資源寫的能力。那麼回過頭去看Resource接口,僅僅定義了讀取資源的能力。
在這裏插入圖片描述

體驗FileSystemResource

在 項目中創立一個文件。test.txt
在這裏插入圖片描述
然後利用Spring的FileSystemResource進行讀寫操作。

public class ResourceDemo {
    public static void main(String[] args) throws IOException {
        FileSystemResource fileSystemResource = new FileSystemResource(
                "E:\\mooc\\熟悉Spring源碼\\src\\main\\java\\com\\fuyouj\\demo\\resource\\test.txt");
        File file = fileSystemResource.getFile();
        System.out.println(file.length());
        //獲取輸出流
        OutputStream outputStream = fileSystemResource.getOutputStream();
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("你好");
        bufferedWriter.flush();
        outputStream.close();
        bufferedWriter.close();
    }
}

可以看到,爲了訪問不同的資源,要通過不同的Resource實現類,那麼可以不顯示使用實現類的情況下,就能夠訪問不同的資源。答案是肯定的,我們平時使用的時候就沒有顯示用這些實現類。
Spring不僅僅帶classpath:,file前綴的資源,還能解析Ant風格的路徑。
Ant風格我們也經常用到。
在這裏插入圖片描述
這種自動適配所有資源的能力是 ResourceLoader賦予的。

ResourceLoader

ResourceLoader實現不同的Resource加載策略,按需返回不同的類型的Resource.
在這裏插入圖片描述
在這裏插入圖片描述

DefaultResourceLoader

DefaultResourceLoader實現了ResourceLoader接口,其中的getResource就是根據地址的不同 返回不同的Resource實例。

@Override
	public Resource getResource(String location) {
		Assert.notNull(location, "Location must not be null");

		for (ProtocolResolver protocolResolver : getProtocolResolvers()) {
			Resource resource = protocolResolver.resolve(location, this);
			if (resource != null) {
				return resource;
			}
		}

		if (location.startsWith("/")) {
			return getResourceByPath(location);
		}
		else if (location.startsWith(CLASSPATH_URL_PREFIX)) {
			return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader());
		}
		else {
			try {
				// Try to parse the location as a URL...
				URL url = new URL(location);
				return (ResourceUtils.isFileURL(url) ? new FileUrlResource(url) : new UrlResource(url));
			}
			catch (MalformedURLException ex) {
				// No URL -> resolve as resource path.
				return getResourceByPath(location);
			}
		}
	}

ResourcePatternResolver

回到ResouceLoader接口,觀察裏面的

Resource getResource(String location);

方法發現僅僅支持路徑地址的解析,而不能滿足Ant風格,所以 ResourcePatternResolver正是提供了這樣的能力。
在這裏插入圖片描述
繼續觀察類圖,
在這裏插入圖片描述
可以看到熟悉的 Application容器接口,因此可以說,Spring中的容器具有解析任意資源的能力。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章