1.構建應用上下文
一個應用上下文構造器一般需要一個構成Bean定義的上下為你xml字符串路徑或者一個字符串數組路徑作為參數。
當這樣的路徑沒有前綴的時候,那么從哪個路徑構建的資源類型,用於加載bean的定義,取決於它所處的指定的上下文環境,例如,如果你像下面一樣創建一個ClassPathXMLApplicationContext :
ApplicationContext ctx = new ClassPathXmlApplicationContext("conf/appContext.xml");
Bean定義將會從classpath中加載然后做完一個ClassPathResource來使用。但還如果你像下面這樣創建改一個FileSystemXxmlApplicationContext:
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/appContext.xml");
Bean定義將會從一個文件出被加載,在這個例子中將會從想對你的當前工作目錄中查看。
注意在位置中中的明確的Classpath前綴或者標准的URL前綴將會覆蓋缺省的創建用於加載定義的Resource類型。所以這個FileSystemXmlApplicationContext...
ApplicationContext ctx =
new FileSystemXmlApplicationContext("classpath:conf/appContext.xml");
它將會從classpath中加載bean定義。但是,這仍然是一個FileSystemXmlApplicationContext。如果它經常被當成一個ResourceLoader,那么任何不帶前綴的路徑將會被當成是文件路徑。
1.1.構建ClassPathXmlApplicationContext-快捷方式
ClassPathXmlApplicationContext提供了大量的構造函數來提供實例化的操作。設計的基本做法就是一個提供包含xml文件名稱的字符串數組,而一個銅是提供了一個類:ClassPathXmlApplicationContext從提供的類中發現路徑的信息。
下面的例子將吧這個表述的很清晰。看下面的文件夾布局:
com/
foo/
services.xml
daos.xml
MessengerService.class
ClassPathXmlApplicationContext實例有在servies.xml和daos.xml中定義的beans組成,可以向下面這樣被實例化:
ApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] { "services.xml", "daos.xml"}, MessengerService. class);
2.在應用上下文構造函數中資源路徑的通配符
在應用上下文構造函數的值中的資源路徑可能是一個只是一對一映射到目標資源的簡單的路徑或者是包含特殊的“classpath*:”前綴或者的ANT風格的表達式。后者都是通配符的應用。
使用這種機制的場景之一就是當來處理組件風格的應用。所有的組件能夠發布上下文定義的代碼片段,而且當最終的應用上下文通過使用相同的路徑前綴被創建的 時候,所有的組件片段能夠自動的裝配在一起。
注意到這個通配符是指定用在資源路徑中的 ,而且在構建的時候被解析。它和Resource類型自身沒有關系。不要使用前綴classpath*:來構建構建一個真正的資源,因為一個資源只會一次指向一個資源。
2.1 ANT風格的模式
當路徑含有ANT風格模式的時候:
/WEB-INF/-context.xml
com/mycompany//applicationContext.xml
file:C:/some/path/-context.xml
classpath:com/mycompany//applicationContext.xml
解析器會根據這個復雜但是被定義的過程去解析通配符。它會根據上下的非通配符中獲取一個Resource而且從一個URL獲取。如果這個URL不是一個jar,URL或者容器指定的變體,然后一個java.io.File就會通過它獲取而且通過文件系統來解析這個通配符。在一個Jar URL中,解析器會獲取一個java.net.JarURLConnection或者可以手動解析這個Jar URL然后通過j意義上的可移植性
ar文件內容來解析通配符。
2.1.1意義上的可移植性
如果指定的路徑已經是一個文件URL了,不管是隱式的還是現實的,因為基礎的ResourceLoader是一個文件系統了,然后通配符就會保證工作在一個完全便攜的風格中。
如果指定的路徑是一個classpath位置,那么解析器就必須通過一個Classloader.getResource() 方法調用獲取最后一個非通配符路徑的URL片段。因為這個只是路徑的一個,嚴格來說它是未定義的。在實踐中,一般它是java.io.File來表示一個目錄。一般在這個操作中還有移植行的考慮。
如果一個Jar URL 作為最后一個非通配符片段來獲取,解析器必須能從這里面夠獲取一個java.net.JarURLConnection,或者手動解析這個Jar URL,一般能夠讀取Jar的內容並且解析通配符。這個在發布費的環境中會有效但是在一些中會出錯,而且強烈建議通過通配符的方式從jar中獲取資源需要在你你指定的環境中得到測試在你使用它之前。
2.2Classpath: classpath: 前綴
當構造一個基於XML的應用上下文的時候,一個特殊的classpath*:前綴:
ApplicationContext ctx =
new ClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
這個特殊的前綴明確了所有classpath資源必須匹配給定的名字才會被獲取然后組合在一起形成了最終的應用上下文的定義。
" classpath: "需要和一個PathMatcher模式聯系在一起,例如 " classpath:META-INF/*-beans.xml"。在這個例子里,解決策略是想淡定簡單:一個ClassLoader.getResources()調用在后面的非通配符片段中獲取所有匹配的資源,然后應用相同的匹配策略對於子路徑。
2.2.1關於通配符的其他說明
請注意 " classpath:"在和ANT風格的模式聯系在一起的時候在模式開始之前只會在一個根目錄出開始匹配,出發實際的目標文件在文件系統中。這意味着像“classpath😗.xml”不會從jar文件的根路徑來檢出文件而是從擴展的目錄的跟路徑出。這個起源於JDK中的只返回傳入空的字符串的文件系統的位置的ClassLoader.getResources()方法的限制。
有找" classpath: "的ANT風格的資源都不確定一定會找到匹配的資源如果根包的搜索在多各類的路徑位置處的時候,這是因為像這樣的一個資源:
com/mycompany/package1/service-context.xml
可能只是一個位置,但是當一個路徑像這樣:
classpath:com/mycompany/**/service-context.xml
當試找去解析它的時候,這個解析器將會返回 getResource("com/
mycompany") ;第一個的URL;如果根包節點在多個classLoader位置中存在的話,實際的結束的資源可能不是在下面。因此,在這個例子中更好的使用相同的ANT風格 " classpath*: " ,它將會搜索包含根包的所有的類路徑。
2.3FileSystemResource說明
沒有綁定到FileSystemApplicationContext 的FileSystemResourcey也會被完全當成是你所期望的對的相對路徑。相對的路徑就是相對於當前的工作目錄,當決定路徑是相對於文件的 根目錄是。
由於向后兼容的原因,當FileSystemApplicationContext是ResourceLoader的改變。FileSystemApplicationContext簡單的 強迫所有的綁定的FileSystemResource實例把所有的位置路徑當做相對的,不管他們是否一個開始還是不是。在實際中,這意味着下面是等價的:
ApplicationContext ctx =
new FileSystemXmlApplicationContext("conf/context.xml");
ApplicationContext ctx =
new FileSystemXmlApplicationContext("/conf/context.xml");
正如下面一樣:
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 its definition via a UrlResource
ApplicationContext ctx =
new FileSystemXmlApplicationContext("file:/conf/context.xml");