?
Dieses Dokument verwendet PHP-Handbuch für chinesische Websites Freigeben
application context構造器通常使用字符串或字符串數組作為資源(比如組成context定義 的XML文件)的定位路徑。
當這樣的定位路徑沒有前綴時,指定的 Resource
類型會通過這個路徑來被創(chuàng)建并被用來載入bean的定義,這都取決于你所指定的application context。例如,如果你使用下面的代碼來創(chuàng)建ClassPathXmlApplicationContext
:
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
這些Bean的定義會通過classpath載入并使用ClassPathResource
。而如果你象下面這么創(chuàng)建FileSystemXmlApplicationContext
:
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/appContext.xml");
這些Bean的定義會通過文件系統(tǒng)從相對于當前工作目錄中被載入。
請注意如果定位路徑使用classpath前綴或標準的URL前綴,那它就會覆蓋默認的Resource
類型。因此下面的FileSystemXmlApplicationContext
...
ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
...實際上會通過classpath載入其bean定義。然而它仍是個FileSystemXmlApplicationContext
。
如果后面它被當作ResourceLoader
來使用,那么任何沒有使用前綴的路徑依然會被當作一個文件系統(tǒng)路徑。
ClassPathXmlApplicationContext
提供了多種構造方法以便于初始化。但其核心是,如果我們僅僅提供由XML文件名組成的字符串數組(沒有完整路徑信息), 而且還提供了Class
;那么該ClassPathXmlApplicationContext
就
會從給定的類中抽取路徑信息。
希望通過一個示例把這些闡述清楚。假設有這樣的目錄結構:
com/ foo/ services.xml daos.xml MessengerService.class
由 'services.xml'
和 'daos.xml'
中定義的bean組成的
ClassPathXmlApplicationContext
實例會象這樣地來實例化...
ApplicationContext ctx = new ClassPathXmlApplicationContext( new String[] {"services.xml", "daos.xml"}, MessengerService.class);
欲了解 ClassPathXmlApplicationContext
多種構造方法的細節(jié),請參考它的Javadocs。
Application context構造器中資源路徑的值可以是簡單的路徑(就像上面的那樣),即一對一映射到一個目標資源;
或者可以包含特殊的"classpath*:"前綴和Ant風格的正則表達式(用Spring的 PathMatcher
工具來匹配)。
后面的二者都可以使用通配符。
該機制的一個用處就是做組件類型的應用組裝。所有的組件都可以用通用的定位路徑“發(fā)布”context定義片斷,
這樣當使用相同的 classpath*:
前綴創(chuàng)建最終的application context時,所有的組件片斷都會被自動裝入。
請注意,這個通配符只在application context構造器的資源路徑中
(或直接在類的層次中使用 PathMatcher
工具時)有效,
它會在構造時進行解析。這與 Resource
類型本身沒有關聯(lián)。因為同一時刻只能指向一個資源,所以不能使用
classpath*:
前綴來構造實際的Resource
。
在包含Ant風格的pattern時,例如:
/WEB-INFapplicationContext.xml file:C:/some/pathapplicationContext.xml
解析器會進行一個預先定義的復雜的過程去試圖解析通配符。
它根據路徑中最后一個非通配符片斷產生一個Resource并從中獲得一個URL。
如果這個URL不是一個"jar:" URL或特定容器的變量(例如WebLogic中的
"zip:
",WebSphere中的"wsjar
"等等),
那么可以從中獲得一個java.io.File
,
并用它從文件系統(tǒng)中解析通配符。如果是一個jar URL,解析器可以從中取得一個
java.net.JarURLConnection
,或者手工解析該jar URL,
隨后遍歷jar文件以解析通配符。
如果給定的路徑已經是一個文件URL(可以是顯式的或者是隱式的), 由于基本的ResourceLoader是針對文件系統(tǒng)的,那么通配符一定能夠移植。
如果給定的路徑是一個classpath的位置,那么解析器必須通過一個
Classloader.getResource()
調用獲得最后一個
非通配符路徑片斷的URL。因為這僅僅是一個路徑的節(jié)點(不是最終的文件),
所以它并未確切定義(在 ClassLoader
Javadocs里)
此處究竟會返回什么類型的URL。一般情況下,當classpath資源解析為一個文件系統(tǒng)位置時,
返回一個代表目錄的 java.io.File
;當解析為jar位置時,
返回某類jar URL。當然,這個操作涉及到可移植性。
如果從最后一個非通配符片斷中獲得一個jar URL,那么解析器一定能從中取得一個
java.net.JarURLConnection
,或者手動解析jar URL以遍歷jar文件,
從而解析通配符。這一操作在大多數環(huán)境中能正常工作,不過也有例外,
因此我們強烈建議特定環(huán)境中的jar資源通配符解析應在正式使用前要經過徹底測試。
當構造基于XML的application context時,路徑字符串可能使用特殊的 classpath*:
前綴:
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
此前綴表示所有與給定名稱匹配的classpath資源都應該被獲取(其中,這經常會在調用 ClassLoader.getResources(...)
) 時發(fā)生),并接著將那些資源全并成最終的application context定義。
帶通配符的classpath依賴于底層classloader的 getResources()
方法。
現(xiàn)在大多數的應用服務器提供自己的classloader實現(xiàn),它們在處理jar文件時的行為也許會有所不同。
要測試 classpath*:
是否有效,可以簡單地用classloader從classpath中的jar文件里加載一個文件:
getClass().getClassLoader().getResources("<someFileInsideTheJar>")
。
針對兩個不同位置但有相同名字的文件來運行測試。如果結果不對,那么就查看一下應用服務器的文檔,
特別是那些可能影響classloader行為的設置。
" 解析器會排除classpath*:
"前綴也能在位置路徑的其他部分結合PathMatcher
pattern一起使用,例如"classpath*:META-INFservice-context.xml
getResource("com/mycompany")
;返回的(第一個)URL。
如果這個基礎包節(jié)點存在于多個classloader位置,最終要找的資源未必會被發(fā)現(xiàn)。
因此在這種情況中最好在這個Ant風格的pattern中使用"classpath*:
",
這樣就會搜索包含根包在內所有類路徑。
一個并沒有與 FileSystemApplicationContext
綁定的
FileSystemResource
(也就是說FileSystemApplicationContext
并不是真正的ResourceLoader
),會象你期望的那樣分辨絕對和相對路徑。
相對路徑是相對于當前的工作目錄,而絕對路徑是相對與文件系統(tǒng)的根目錄。
為了向前兼容的目的,當 FileSystemApplicationContext
是個
ResourceLoader
時它會發(fā)生變化。FileSystemApplicationContext
會簡單地讓所有綁定的 FileSystemResource
實例把絕對路徑都當成相對路徑,
而不管它們是否以反斜杠開頭。也就是說,下面的含義是相同的:
ApplicationContext ctx = new FileSystemXmlApplicationContext("conf/context.xml");
ApplicationContext ctx = new FileSystemXmlApplicationContext("/conf/context.xml");
下面的也一樣:(雖然把它們區(qū)分開來也很有意義,但其中的一個是相對路徑而另一個則是絕對路徑)。
FileSystemXmlApplicationContext ctx = ...; ctx.getResource("some/resource/path/myTemplate.txt");
FileSystemXmlApplicationContext ctx = ...; ctx.getResource("/some/resource/path/myTemplate.txt");
實際上如果的確需要使用絕對路徑,那你最好就不要使用 FileSystemResource
或 FileSystemXmlApplicationContext
來確定絕對路徑。我們可以通過使用 file:
URL前綴來強制使用UrlResource
。
// actual context type doesn't matter, the Resource
will always be UrlResource
ctx.getResource("file:/some/resource/path/myTemplate.txt");
// force this FileSystemXmlApplicationContext to load it's definition via a UrlResource
ApplicationContext ctx =
new FileSystemXmlApplicationContext("file:/conf/context.xml");