Resource理解

1、什麼是Resource

當咱們學習Spring時,咱們總會在xml中對bean進行聲明,而後再經過下面的代碼片斷來獲取bean。代碼以下:java

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Context {

  public static void main(String[] args) {
    
    ApplicationContext ctx = new ClassPathXmlApplicationContext("Spring.xml");//一、加載配置文件
    System.err.println(ctx.getBean("stu").toString());//二、經過配置文件獲取一個bean並打印

   }
}

上面第一行代碼加載了一個資源文件Spring.xml,這個資源文件在Spring中屬於Resource的一種。這樣講,Spring把各類類型的文件,二進制流都稱之爲Resource,只不過對於Spring開發者來講,Resource大多都是xml文件。web

Resource是一個接口,接口裏邊定義了很是多關於文件的操做策略,好比spring

  • exists():判斷資源是否存在
  • getURL():獲取資源的URL
  • getFilename():獲取資源的名稱
  • ......(方法很是多,我就不一一列舉了)

Resource 接口是具體資源訪問策略的抽象,也是全部資源訪問類所實現的接口。Resource 接口自己沒有提供訪問任何底層資源的實現邏輯,針對不一樣的底層資源,Spring 將會提供不一樣的 Resource 實現類,不一樣的實現類負責不一樣的資源訪問邏輯。數據庫

很是重要的一點,這也是Spring Resource設計最美妙的地方,那就是Spring 在Resource資源處理上採用啦策略模式,這也是我爲何上面把Resource接口中的方法稱之爲策略的緣由了!api

若是還不瞭解Java 策略模式的朋友請先自行學習!數組

2、Spring Resource接口類結構圖

爲了更好地理解,在這裏我先放一張策略模式的UML圖,它的具體內容本文不講。函數

 

 

 

 

好了!圖片放上去了,那麼策略模式Resource體系上如何體現出來呢?學習

  • 一、Resource接口至關於咱們的策略
  • 二、下面全部的實現類,包括AbstractResource在內都屬於咱們的具體策略實現
  • 三、你可能要問,那麼咱們的context角色到哪裏去了呢?哈哈,作生意不能忘了咱們的老本啊!它就是咱們的IOC容器ApplicationContext,它是咱們策略模式中最最最具備決策能力的老大了

至於爲何容器就能夠處理咱們的Resource,我接下去會說到!spa

很明顯,Resource是資源的最高抽象,一般咱們的應用程序不是都從classpath下去加載咱們的xml文件,咱們也能夠經過一個URL,URI,InputStream等方式獲取一個資源,這就是Spring把資源的獲取方式和資源的定義之間解耦了!.net

3、ResourceLoader接口

  • ResourceLoader:該接口實現類的實例能夠得到一個 Resource 實例。。

ResourceLoader 接口裏有以下方法:

  • Resource getResource(String location):該接口僅包含這個方法,該方法用於返回一個 Resource 實例。

ApplicationContext 的實現類都實現 ResourceLoader 接口,而該接口又返回一個Resource實例,所以 ApplicationContext 可用於直接獲取 Resource 實例,這也是爲何容器就能夠處理Resource的緣由!

4、spring 直接提供了多種開箱即用的 Resource 實現

1.UrlResource


UrlResource 封裝了一個 java.net.URL 對象,用來訪問 URL 能夠正常訪問的任意對象,好比文件、an HTTP target, an FTP target, 等等。全部的 URL 均可以用一個標準化的字符串來表示。如經過正確的標準化前綴,能夠用來表示當前 URL 的類型,當中就包括用於訪問文件系統路徑的 file:,經過 http 協議訪問資源的 http:,經過 ftp 協議訪問資源的 ftp:,還有不少……

能夠顯式化地使用 UrlResource 構造函數來建立一個 UrlResource,不過一般咱們能夠在調用一個 api 方法是,使用一個表明路徑的 String 參數來隱式建立一個 UrlResource。對於後一種狀況,會由一個 javabean PropertyEditor 來決定建立哪種 Resource。若是路徑裏包含某一個通用的前綴(如 classpath:),PropertyEditor 會根據這個通用的前綴來建立恰當的 Resource;反之,若是 PropertyEditor 沒法識別這個前綴,會把這個路徑做爲一個標準的 URL 來建立一個 UrlResource。

2.ClassPathResource


可使用 ClassPathResource 來獲取類路徑上的資源。ClassPathResource 可使用線程上下文的加載器、調用者提供的加載器或指定的類中的任意一個來加載資源。

ClassPathResource 能夠從類路徑上加載資源,其可使用線程上下文加載器、指定加載器或指定的 class 類型中的任意一個來加載資源。

當類路徑上資源存於文件系統中,ClassPathResource 支持以 java.io.File 的形式訪問,可當類路徑上的資源存於還沒有解壓(沒有 被Servlet 引擎或其餘可解壓的環境解壓)的 jar 包中,ClassPathResource 就再也不支持以 java.io.File 的形式訪問。鑑於上面所說這個問題,spring 中各式 Resource 實現都支持以 jave.net.URL 的形式訪問。

能夠顯式使用 ClassPathResource 構造函數來建立一個 ClassPathResource ,不過一般咱們能夠在調用一個 api 方法時,使用一個表明路徑的 String 參數來隱式建立一個 ClassPathResource。對於後一種狀況,會由一個 javabean PropertyEditor 來識別路徑中 classpath: 前綴,從而建立一個 ClassPathResource。

3.FileSystemResource

這是針對 java.io.File 提供的 Resource 實現。顯然,咱們可使用 FileSystemResource 的 getFile() 函數獲取 File 對象,使用 getURL() 獲取 URL 對象。

4.ServletContextResource

這是爲了獲取 web 根路徑的 ServletContext 資源而提供的 Resource 實現。

ServletContextResource 徹底支持以流和 URL 的方式訪問,可只有當 web 項目是已解壓的(不是以 war 等壓縮包形式存在)且該 ServletContext 資源存於文件系統裏,ServletContextResource 才支持以 java.io.File 的方式訪問。至於說到,咱們的 web 項目是否已解壓和相關的 ServletContext 資源是否會存於文件系統裏,這個取決於咱們所使用的 Servlet 容器。若 Servlet 容器沒有解壓 web 項目,咱們能夠直接以 JAR 的形式的訪問,或者其餘能夠想到的方式(如訪問數據庫)等。

5.InputStreamResource

這是針對 InputStream 提供的 Resource 實現。建議,在確實沒有找到其餘合適的 Resource 實現時,才使用 InputSteamResource。若是能夠,儘可能選擇 ByteArrayResource 或其餘基於文件的 Resource 實現來代替。

與其餘 Resource 實現已比較,InputStreamRsource 倒像一個已打開資源的描述符,所以,調用 isOpen() 方法會返回 true。除了在須要獲取資源的描述符或須要從輸入流屢次讀取時,都不要使用 InputStreamResource 來讀取資源。

6.ByteArrayResource

這是針對字節數組提供的 Resource 實現。能夠經過一個字節數組來建立 ByteArrayResource。

當須要從字節數組加載內容時,ByteArrayResource 是一個不錯的選擇,使用 ByteArrayResource 能夠不用求助於 InputStreamResource。

5、策略模式在Spring中使用有什麼優點

Spring 應用須要進行資源訪問時,實際上並不須要直接使用 Resource 實現類,而是調用 ApplicationContext 實例的 getResource() 方法來得到資源,ApplicationContext 將會負責選擇 Resource 的實現類,也就是肯定具體的資源訪問策略,從而將應用程序和具體的資源訪問策略分離開來。

既然有那麼多的優點,下面就在來解釋咱們上面的第一段代碼,爲何要使用ClassPathXmlApplicationContext這個類來對資源進行加載?

咱們都知道,在容器ApplicationContext下有不少的實現,好比FileSystemXmlApplicationContext,ClassPathXmlApplicationContext,XmlWebApplicationContext,並且咱們加載配置文件的方式一般也是使用它們來進行加載,在Spring中,ApplicationContext的實現類顧名思義也是對應了咱們Resource接口的一些實現策略,好比ClassPathResource,FileSystemResource等。

相關文章
相關標籤/搜索