classpath:applicationContext-config.xml表示當前項目中載入設定檔 classpath*:applicationContext-config.xml表示從jar包中載入設定檔 在應用Spring的工程中,使用class path的方式載入設定檔應該是最常用的做法,然而對大部分人來說,剛開始使用Spring時,幾乎都碰到過載入設定檔失敗的情況,除了配置上的錯誤外,很多時候是因為設定檔的路徑和程式中指定的載入路徑不一致,從而導致設定檔找不到,或是載入了錯誤地方的設定檔。本文將就Spring如何從class path中載入設定檔做一些簡要的分析。 情形一:使用classpath載入且不含萬用字元 這是最簡單的情形,Spring預設會使用當前線程的ClassLoader的getResource方法擷取資源的URL,如果無法獲得當前線程的ClassLoader,Spring將使用載入類org.springframework.util.ClassUtils的ClassLoader。 1.當工程目錄結構: 即設定檔放在bin目錄中的conf檔案夾裡,這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("conf/application-context.xml");來建立ApplicationContext對象的話,Spring將載入bin/conf目錄下的application-context.xml檔案。Spring啟動時的輸出顯示為: Loading XML bean definitions from class path resource [conf/application-context.xml] 2.當工程目錄結構: 即bin目錄下只有.class檔案,沒有設定檔,同時在工程屬性的Java Build Path->Libraries裡匯入conf.jar檔案,jar檔案結構: 這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("conf/application-context.xml");來建立ApplicationContext對象的話,Spring將載入conf.jar檔案中conf目錄下的application-context.xml檔案。Spring啟動時的輸出顯示為: Loading XML bean definitions from class path resource [conf/application-context.xml] 3. 當工程目錄結構: 即設定檔放在bin目錄中的conf檔案夾裡,同時在工程屬性的Java Build Path->Libraries裡匯入conf.jar檔案,jar檔案結構: 這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("conf/application-context.xml");來建立ApplicationContext對象的話,由於沒有使用classpath*首碼,Spring只會載入一個application-context.xml檔案。在eclipse中將會載入bin/conf目錄下的application-context.xml檔案,而jar包中的conf/application-context.xml並不會被載入,Spring啟動時的輸出顯示為: Loading XML bean definitions from class path resource [conf/application-context.xml] 情形二:使用classpath載入,包含萬用字元 碰到萬用字元的情況時,Spring會通過使用路徑中的非萬用字元部分先確定資源的一般位置,然後根據這個位置在確定具體的資源位置,結合下面給出的幾種情況可以更好地理解Spring的這種工作方式 1. 當工程目錄結構: 即設定檔放在bin目錄中的conf檔案夾裡,這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("conf/**/*application-context.xml"); 來建立ApplicationContext對象的話,Spring首先會通過路徑中的非萬用字元部分即conf,先確定conf的路徑,即bin/conf目錄,然後從該目錄下載入設定檔,由於使用了/**/的方式,表明要載入conf目錄下包括各級子目錄中的所有設定檔,因此bin/conf/application-context.xml檔案和 bin/conf/admin/admin-application-context.xml都會被載入,Spring啟動時的輸出顯示為: Loading XML bean definitions from file [D:\myworkspace\spring-study\bin\conf\admin\admin-application-context.xml] Loading XML bean definitions from file [D:\myworkspace\spring-study\bin\conf\application-context.xml] 2.當工程目錄結構: 即bin目錄下只有.class檔案,沒有設定檔,同時在工程屬性的Java Build Path->Libraries裡匯入conf.jar檔案,jar檔案結構: 這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("conf/**/*application-context.xml");來建立ApplicationContext對象的話,Spring首先會通過路徑中的非萬用字元部分即conf,先確定conf的路徑,即conf.jar中的conf目錄,然後從該目錄下載入設定檔,由於使用了/**/的方式,表明要載入conf目錄下包括各級子目錄中的所有設定檔,因此conf/application-context.xml檔案和 conf/admin/admin-application-context.xml都會被載入,Spring啟動時的輸出顯示為: Loading XML bean definitions from class path resource [conf/admin/admin-application-context.xml] Loading XML bean definitions from class path resource [conf/application-context.xml] 3.當工程目錄結構: 即設定檔放在bin目錄中的conf檔案夾裡,同時在工程屬性的Java Build Path->Libraries裡匯入conf.jar檔案,jar檔案結構: 這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("conf/**/*application-context.xml");來建立ApplicationContext對象的話,Spring首先會通過路徑中的非萬用字元部分即conf,先確定conf的路徑,在eclipse中是bin/conf目錄,然後從該目錄下載入設定檔,由於使用了/**/的方式,表明要載入conf目錄下包括各級子目錄中的所有設定檔,因此bin/conf/application-context.xml檔案和 bin/conf/admin/admin-application-context.xml都會被載入,但conf.jar檔案中的設定檔並不會被載入,Spring啟動時的輸出顯示為: Loading XML bean definitions from file [D:\myworkspace\spring-study\bin\conf\admin\admin-application-context.xml] Loading XML bean definitions from file [D:\myworkspace\spring-study\bin\conf\application-context.xml] 情形三:使用classpath*首碼且不包含萬用字元 使用classpath*首碼可以擷取所有與給定路徑匹配的classpath資源,從而避免出現兩個不同位置有相同名字的檔案,Spring只載入其中一個的情況。 當工程目錄結構: 即設定檔放在bin目錄中的conf檔案夾裡,同時在工程屬性的Java Build Path->Libraries裡匯入conf.jar檔案,jar檔案結構: 這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:conf/application-context.xml");來建立ApplicationContext對象的話, Spring將會載入bin目錄下的application-context.xml檔案和jar包裡的application-context.xml檔案,Spring啟動時的輸出顯示為: Loading XML bean definitions from URL Loading XML bean definitions from URL [jar:file:/D:/myworkspace/conf1.jar!/conf/application-context.xml] Spring中使用classpath載入設定檔淺析(續) 情形四:使用classpath*首碼,包含萬用字元 當工程目錄結構: 即設定檔放在bin目錄中的conf檔案夾裡,同時在工程屬性的Java Build Path->Libraries裡匯入conf.jar檔案,jar檔案結構: 這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:conf/**/*application-context.xml");來建立ApplicationContext對象的話,Spring首先會通過路徑中的非萬用字元部分即conf,先確定conf的路徑,由於使用了classpaht*首碼,因此bin目錄下的conf和jar包裡的conf都會被載入,同時由於使用了/**/的方式,表明要載入conf目錄下包括各級子目錄中的所有設定檔,因此bin/conf/application-context.xml和 bin/conf/admin/admin-application-context.xml以及jar包中的 conf/application-context.xml和 conf/admin/admin-application-context.xml都會被載入,Spring啟動時的輸出顯示為: Loading XML bean definitions from file [D:\myworkspace\spring-study\bin\conf\admin\admin-application-context.xml] Loading XML bean definitions from file [D:\myworkspace\spring-study\bin\conf\application-context.xml] Loading XML bean definitions from URL [jar:file:/D:/myworkspace/conf1.jar!/conf/admin/admin-application-context.xml] Loading XML bean definitions from URL [jar:file:/D:/myworkspace/conf1.jar!/conf/application-context.xml] 特別注意: 如果工程目錄: 即設定檔直接放在bin目錄中,同時在工程屬性的Java Build Path->Libraries裡匯入conf.jar檔案,jar檔案結構: 這時使用 ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:**/*application-context.xml");來建立ApplicationContext對象的話,Spring只會載入 bin/application-context.xml和bin/admin/admin-application-context.xml, 而jar包中的設定檔並不會被載入。這是因為Spring使用class path載入設定檔時需要藉助JDK的ClassLoader.getResources(String name)方法,而該方法有一個局限:當傳入的參數為空白字串時,即我們本意是想從根目錄擷取檔案,這時JDK只會返回存在於檔案系統中的資源,而在jar包中的資源並不會被返回。 我們在eclipse中寫個簡單的測試類別就能很容易看到這點: ClassLoader loader = Thread.currentThread().getContextClassLoader(); Enumeration resources = loader.getResources(""); while (resources.hasMoreElements()) { URL url = (URL)resources.nextElement(); System.out.println(url); } 運行測試類別後,輸出結果為: file:/D:/myworkspace/spring-study/bin/ file:/D:/ProgramFiles/eclipse3.2/configuration/org.eclipse.osgi/bundles/47/1/.cp/ 可以看到,獲得的資源路徑中並不包含jar包中的路徑,因此jar包中的設定檔自然不能被Spring載入了。 Spring中使用classpath載入設定檔淺析 參考資料: Spring Framework開發參考手冊(中文翻譯版) http://www.redsaga.com/spring_ref/2.0/html/ java.lang.ClassLoader的API文檔 http://java.sun.com/j2se/1.5.0/docs/api/ org.springframework.core.io.support.PathMatchingResourcePatternResolver的API文檔 http://static.springframework.org/spring/docs/2.0.x/api/index.html |