日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

06.Spring 资源加载 - ResourceLoader

發(fā)布時(shí)間:2025/7/25 88 豆豆
生活随笔 收集整理的這篇文章主要介紹了 06.Spring 资源加载 - ResourceLoader 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基本概念

ResourceLoader 接口,在 Spring 中用于加載資源,通過(guò)它可以獲取一個(gè) Resouce 對(duì)象。


內(nèi)部構(gòu)造

首先來(lái)看它的接口定義:

public interface ResourceLoader {// 從 classpath 加載資源時(shí)的前綴 String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX; // 關(guān)鍵-> 取得 Resource 對(duì)象,即獲取資源 Resource getResource(String location); ClassLoader getClassLoader(); }

再來(lái)看它的繼承關(guān)系,如下所示:

  • DefaultResourceLoader?: 作為 ResourceLoader 接口的直接實(shí)現(xiàn)類,該類實(shí)現(xiàn)了基本的資源加載功能,可以實(shí)現(xiàn)對(duì)單個(gè)資源的加載。

  • ResourcePatternResolver?:該接口繼承了 ResourceLoader,定義了加載多個(gè)資源的方法, 可以實(shí)現(xiàn)對(duì)多個(gè)資源的加載。


DefaultResourceLoader

上面介紹過(guò)該類通過(guò)實(shí)現(xiàn) ResourceLoader 接口實(shí)現(xiàn)了加載單個(gè)資源的功能。它的子類通過(guò)繼承它來(lái)實(shí)現(xiàn)具體的資源訪問(wèn)策略。下面來(lái)探究下該類如何加載單個(gè)資源:

public Resource getResource(String location) {Assert.notNull(location, "Location must not be null");// ① 是否以"/" 開頭if (location.startsWith("/")) { return getResourceByPath(location); } // ② 是否以"classpath:" 開頭,若是則表示該資源類型為 ClassPathResource else if (location.startsWith(CLASSPATH_URL_PREFIX)) { return new ClassPathResource(location.substring(CLASSPATH_URL_PREFIX.length()), getClassLoader()); } else { try { // ③若都不是,則當(dāng)成 UrlResource 來(lái)處理 URL url = new URL(location); return new UrlResource(url); }catch (MalformedURLException ex) { // 若不是 UrlResource,則仍當(dāng)作 ① 情況來(lái)處理 return getResourceByPath(location); } } }

觀察代碼,發(fā)現(xiàn)在拿到資源的路徑?loaction?后,會(huì)根據(jù) location 的形式分成三種情況來(lái)處理:

  • 以 “/” 開頭:默認(rèn)調(diào)用類中的?getResourceByPath?方法處理。它的子類通過(guò)重寫該方法實(shí)現(xiàn)不同形式的資源的訪問(wèn)。

  • 以 “classpath:” 開頭:當(dāng)成?ClassPathResource?資源對(duì)待。

  • 其他情況: 當(dāng)成?UrlResource?資源對(duì)待,如果訪問(wèn)資源拋出異常,則調(diào)用 getResourceByPath 來(lái)完成資源的訪問(wèn)。


ResourcePatternResolver

該接口繼承自 ResourceLoader 接口,在其基礎(chǔ)上增加了同時(shí)對(duì)多個(gè)資源的訪問(wèn)。首先來(lái)看它的接口定義:

public interface ResourcePatternResolver extends ResourceLoader { String CLASSPATH_ALL_URL_PREFIX = "classpath*:"; // 例如使用 ant 風(fēng)格的路徑,匹配路徑下的多個(gè)資源 Resource[] getResources(String locationPattern) throws IOException; }

1.PathMatchingResourcePatternResolver

該類是 ResourcePatternResolver 接口的直接實(shí)現(xiàn)類,它是基于模式匹配的,默認(rèn)使用AntPathMatcher 進(jìn)行路徑匹配,它除了支持 ResourceLoader 支持的前綴外,還額外支持?“classpath*”?,下面來(lái)探究下該類是如何實(shí)現(xiàn)對(duì)多個(gè)資源的訪問(wèn)。

public Resource[] getResources(String locationPattern) throws IOException {Assert.notNull(locationPattern, "Location pattern must not be null");// 是否以 "classpath*:" 開頭 if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) { // 通過(guò) getPathMatcher 方法取得 PathMatcher ,默認(rèn)只有 AntPathMatcher 一個(gè)實(shí)現(xiàn)類 // 通過(guò) isPattern 方法判斷 "classpath*:" 之后的路徑是否包含 "*" 或 "?" if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) { // 關(guān)鍵 -> 找到所有匹配路徑(ant 風(fēng)格)的資源 return findPathMatchingResources(locationPattern); }else { // 關(guān)鍵 -> 通過(guò)類加載器查找 return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length())); } }else { int prefixEnd = locationPattern.indexOf(":") + 1; // 判斷資源路徑 ":" 之后的部分是否包含 "*" 或 "?" if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) { return findPathMatchingResources(locationPattern); }else { // 若不存在表示是單個(gè)資源,則通過(guò)從構(gòu)造函數(shù)傳入的 ResourceLoader 取得 return new Resource[] {getResourceLoader().getResource(locationPattern)}; } } }

觀察代碼:

  • 該方法首先會(huì)去判斷資源路徑是否是類路徑下的資源(以 “classpath*:” 開頭),然后再去判斷路徑是否允許存在多個(gè)匹配的資源(路徑中包含 “*” 或 “?”)。

  • 只要資源路徑允許多個(gè)匹配的資源,就會(huì)通過(guò) findPathMatchingResources 方法尋找所有的匹配資源;

  • 若資源路徑只存在單個(gè)匹配,則通過(guò)類加載器尋找類路徑下的資源(findAllClassPathResources) ,其他資源則通過(guò) ResourceLoader 的 getResource 方法獲取。


2.ApplicationContext

通過(guò)上面的繼承關(guān)系圖可知,該接口繼承了 ResourcePatternResolver 接口,說(shuō)明它也集成了對(duì)對(duì)單個(gè)或多個(gè)資源的訪問(wèn)功能。

當(dāng) Spring 需要進(jìn)行資源訪問(wèn)時(shí),實(shí)際上并不需要直接使用 Resource?實(shí)現(xiàn)類,而是調(diào)用?getResource?方法來(lái)獲取資源。

當(dāng)通過(guò) ApplicationContext 實(shí)例獲取 Resource 實(shí)例時(shí),它將會(huì)負(fù)責(zé)選擇具體的 Resource 的實(shí)現(xiàn)類。代碼如下:

//通過(guò) ApplicationContext訪問(wèn)資源Resource res = ctx.getResource("some/resource/path/myTemplate.txt);

從上面代碼中無(wú)法確定 Spring 將哪個(gè)實(shí)現(xiàn)類來(lái)訪問(wèn)指定資源,Spring 將采用和 ApplicationContext 相同的策略來(lái)訪問(wèn)資源。也就是說(shuō):如果 ApplicationContext 是 FileSystemXmlApplicationContext,res 就是 FileSystemResource 實(shí)例;如果 ApplicationContext 是 ClassPathXmlApplicationContext,res 就是 ClassPathResource 實(shí)例;如果 ApplicationContext 是 XmlWebApplicationContext,res 是 ServletContextResource 實(shí)例。

也就是說(shuō) ApplicationContext 將會(huì)確定具體的資源訪問(wèn)策略,從而將應(yīng)用程序和具體的資源訪問(wèn)策略分離開來(lái),這就體現(xiàn)了策略模式的優(yōu)勢(shì)。


參考

  • https://www.ibm.com/developerworks/cn/java/j-lo-spring-resource/

轉(zhuǎn)載于:https://www.cnblogs.com/moxiaotao/p/9349532.html

總結(jié)

以上是生活随笔為你收集整理的06.Spring 资源加载 - ResourceLoader的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。