前面的三篇文章,主要用beanfactory介紹了spring中ioc容器的兩個階段:容器啟動階段和執行個體化階段。接下來的這篇文章主要說的是spring的統一資源定位政策。
寫下這篇文章之前的絕大部分時間,我都在思考,為什麼要整這個功能。任何一個功能、實作肯定有其道理。那道理是什麼呢?有人是這麼解釋的:
要搞清楚spring為什麼提供這麼一個功能,還是從java se提供的标準類java.net.url說起比較好。url全名是uniform resource locator(統一資源定位器),但多少有些名不副實的味道。 首先,說是統一資源定位,但基本實作卻隻限于網絡形式釋出的資源的查找和定位工作,基本上隻提供了基于http、ftp、file等協定(sun.net.www.protocol 包下所支援的協定)的資源定位功能。雖然也提供了擴充的接口,但從一開始,其自身的“定位”就已經趨于狹隘了。實際上,資源這個詞的範圍比較廣義,資源可以任何形式存在,如以二進制對象形式存在、以位元組流形式存在、以檔案形式存在等;而且,資源也可以存在于任何場所,如存在于檔案系統、存在于java應用的classpath中,甚至存在于url可以定位的地方。 其次,從某些程度上來說,該類的功能職責劃分不清,資源的查找和資源的表示沒有一個清晰的界限。目前情況是,資源查找後傳回的形式多種多樣,沒有一個統一的抽象。理想情況下,資源查找完成後,傳回給用戶端的應該是一個統一的資源抽象接口,用戶端要對資源進行什麼樣的處理,應該由資源抽象接口來界定,而不應該成為資源的定位者和查找者同時要關心的事情。
以上的這段文字來自《spring揭秘》,寫的非常正确。但是我第一遍看的時候,我大緻還是沒看懂。
可能是我底子确實太差了。也可能是因為寫書,總歸要寫的正式一點,而我對于正式語言的了解能力着實不足。這三大段文字的主要意思就是:
一開始肯定是要先定義一個借口resource
resource
接口提供這些方法,基本上是足夠我們日常使用的,除了這個接口,當然也提供了這些接口的sh實作類。
可以看到,有16個實作類,當然,我們常用的并沒有那麼多,主要有以下幾個
bytearrayresource。将位元組(byte)數組提供的資料作為一種資源進行封裝,如果通過inputstream形式通路該類型的資源,該實作會根據位元組數組的資料,構造相應的bytearray-inputstream并傳回。
classpathresource。該實作從java應用程式的classpath中加載具體資源并進行封裝,可以使用指定的類加載器(classloader)或者給定的類進行資源加載。
filesystemresource。對java.io.file類型的封裝,是以,我們可以以檔案或者url的形式對該類型資源進行通路,隻要能跟file打的交道,基本上跟filesystemresource也可以。
urlresource。通過java.net.url進行的具體資源查找定位的實作類,内部委派url進行具
體的資源操作。
inputstreamresource。将給定的inputstream視為一種資源的resource實作類,較為少用。
可能的情況下,以bytearrayresource以及其他形式資源實作代之。
其實啦,上面說了半天,都是在說resource,有了資源,怎麼去查找,怎麼去定位呢,用resourceloader。
這必然,我猜它就是個接口,這麼簡潔的名字。
resourceloader
事實證明,我想的還是沒錯的,但是這個接口也真是夠簡潔的。
看看實作類吧~
18個,但還是先看畫圈的幾個吧。
defaultresourceloader
這是defaultresourceloader傳回resource的方法,可以看到:
看看location是不是以"/"開頭,如果是傳回classpathcontextresource類型的資源
檢查資源路徑是否以classpath:字首打頭,如果是,則嘗試構造classpathresource類型資源并傳回。
嘗試通過url,根據資源路徑來定位資源,如果沒有抛出malformedurlexception,有則會構造urlresource類型的資源并傳回;
4.如果還是無法根據資源路徑定位指定的資源,則委派getresourcebypath(string) 方法來定位, defaultresourceloader 的getresourcebypath(string)方法預設實作邏輯是,構造classpathresource類型的資源并傳回。
filesystemresourceloader雖然是defaultresourceloader的繼承類,但是在getresourcebypaht方法上就不是傳回classpathresource,而是傳回filesystemresource
前面一直就隻是在講資源,資源定位器,但是,在我們spring的展現又在哪裡?
先看這個圖,很明顯,applicationcontext也是resourceloader。如果再看兩個重要的實作類,你就會懂了。原來如此
classpathxmlapplicationcontext
filesystemxmlapplicationcontext
剩下的,你說一個bean裡面,如果要注入resourceloader,或者要注入resource怎麼辦呢?
可以這麼做
然後配置一下bens.xml
有點複雜诶,你說,applicationcontext不就是資源定位器嗎?為什麼還要再弄一個新的出來呢?
前一小節的兩個接口有用了,resourceloaderaware和applicationcontextaware,他們都能拿到ioc容器本身呀。
看這配置檔案不就隻有一行了,友善。
寫完這篇,基本算是把資源一部分搞懂了一點,但是最近一直在反思,這種總結的辦法,可以我是确實不會用markdown吧,每次花在編輯上的時間就非常多了。還是要想想辦法解決這個問題。