一直以來,寫Spring配置文件,都是把其他配置文件的頭拷貝過來,最多改改版本號,也不清楚哪些是需要的,到底是干嘛的。今天整理一下,拒絕再無腦copy。
一、Spring配置文件常見的配置頭
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <!--中間是配置文件部分--> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="find*" propagation="NOT_SUPPORTED" /> </tx:attributes> </tx:advice> <aop:config> <aop:aspect id="***" ref="***"/> <aop:pointcut id="***" expression="****" /> </aop:config> <!--中間是配置文件部分--> </beans>
重點關注配置文件頭部分,就是寫在<beans >元素里的部分。是不是感覺到熟悉又陌生? 仔細了解后,不會再那么神秘了。
二、什么是XML命名空間
XML 命名空間 是由國際化資源標識符 (IRI) 標識的 XML 元素和屬性集合;該集合通常稱作 XML“詞匯”。在XML中,元素名稱是由開發者定義的,當兩個不同的文檔使用相同的元素名時,就會發生命名沖突。舉個簡單的栗子,命名空間很像 Java 中的包,不同的包下面可以存放相同的類名,只要在引入類時前面加上類的包就可以避免同名類的沖突。
三、XML命名空間的聲明與使用
命名空間被聲明為元素的屬性。並不一定只在根元素聲明命名空間;而是可以在 XML 文檔中的任何元素中進行聲明。聲明的命名空間的范圍起始於聲明該命名空間的元素,並應用於該元素的所有內容,直到被具有相同前綴名稱的其他命名空間聲明覆蓋,其中,元素內容是指該元素的 <opening-tag> 和 </closing-tag> 之間的內容。
例如:上面的命名空間是在 <beans> </beans>元素中聲明的,所有其中聲明的命名空間在這兩個標簽中有效。
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:類似於一個保留字,它只用於聲明命名空間。換言之,xmlns 用於綁定命名空間,但其本身並不綁定到任何命名空間。
aop:這里實際上是將前綴“aop”與命名空間"http://www.springframework.org/schema/aop"(這個URI包含關於命名空間的信息)綁定在一起。通常我們會用一個比較簡短或約定俗成的名字來作為命名空間的前綴(例如這里的aop),但具體使用什么前綴完全取決於個人.自定義命名空間的前綴是合法的。使用有意義的命名空間前綴增強了XML檔的清晰性。所以可以看到我們平時在配置Spring配置文件的時候,前綴名都是aop(切面)、tx(事務)等命名方式。
配置了前綴后,我們使用命名空間前綴如下:
<aop:config> <aop:aspect id="***" ref="***"/> <aop:pointcut id="***" expression="****" /> </aop:config>
這里我們在配置面向切面編程的內容時,使用aop前綴,代表后面的元素(config,aspect等)都是在http://www.springframework.org/schema/aop中定義的。請注意,前綴只用作占位符,並且必須通過可以識別命名空間的 XML 分析器進行解釋才能使用綁定到該前綴的實際命名空間。
單個默認命名空間
我們看到,在配置文件中,beans,bean等元素我們是沒有使用命名空間前綴的。重復限定一個要在命名空間中使用的元素或屬性可能會非常麻煩。
這種情況下,可以聲明一個 默認命名空間。無論在任何時候都只能存在一個默認命名空間。
聲明一個 默認命名空間 意味着,如果 默認命名空間 聲明范圍內的任何元素未使用前綴顯式限定,則該元素將被隱式限定。與帶前綴的命名空間一樣,
默認命名空間 也可以被覆蓋。
默認命名空間聲明方式如下:
xmlns="http://www.springframework.org/schema/beans"
也就是說,在命名空間范圍內,不帶有前綴的元素都是在這個命名空間內的,例如這里的<beans> <bean>等,因為比較常用所以就讓
聲明他們的命名空間為默認的啦,不用每次寫都帶前綴。
四、Spring配置文件配置命名空間
spring 整合了各種工具,並且spring提供了對各種工具的xml scheme 的配置方式,簡化了開發。對於各種工具的xml命名空間的引入,我們也應該有一個比較清楚的認識。Spring在啟動時是要檢驗XML文件的。如果xml空間存在命名空間內沒有的元素是要報錯的。通常情況下,命名空間對應的URI是一個存放XSD的地址,盡管規范沒有這么要求。如果沒有提供schemaLocation,那么Spring的XML解析器會從命名空間的URI里加載XSD文件。
例如我們可以這樣寫:
xmlns="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
則默認的命名空間就是加載指定的xsd文件。
schemaLocation提供了一個xml 命名空間到對應的XSD(Xml Schema Definition)文件的一個映射,它的值由一個或多個URI引用對組成,
兩個URI之間以空白符分隔(空格和換行均可)。第一個URI是定義的 XML命名空間的值,第二個URI給出Schema文檔的實際位置,
Schema處理器將從這個位置讀取Schema文檔,該文檔的targetNamespace必須與第一個URI(XML命名空間的值)相匹配。
這里的注意與下面aop的命名空間URI位置對比一下。
在xsi:schemaLocation后面配置的字符串都是成對的,前面的是命名空間的URI,后面是xsd文件的URI;
比如我們給出的例子(注意這里已經用了一個命名前綴:xsi,這個xsi是在xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 聲明的):
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
這里命名空間aop的值是“http://www.springframework.org/schema/aop”,它對應的xsd文件的位置為“http://www.springframework.org/schema/aop/spring-aop-3.0.xsd”
我們打開http://www.springframework.org/schema/aop/spring-aop-3.0.xsd,可以看到xsd文件中targetNamespace的值和命名空間的值一樣。如下:

五、Spring找到校驗XML的xsd文件
Spring默認在啟動時是要從配置的命名空間的位置加載XSD文件來驗證xml文件的,所以如果有的時候斷網了,或者一些開源軟件切換域名,那么就很容易碰到應用啟動不了。
為了防止這種情況,Spring提供了一種機制,即默認從本地加載XSD文件,當本地沒有時才根據實際的URI去聯網獲得。
我們打開Spring-aop-4.1.6RELEASE.jar (這是我本地的版本),這個包下有一個META_INF文件夾,其中有兩個文件:spring.handlers和spring.schemas。
spring.handlers
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
spring.schemas
http\://www.springframework.org/schema/aop/spring-aop-2.0.xsd=org/springframework/aop/config/spring-aop-2.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-2.5.xsd=org/springframework/aop/config/spring-aop-2.5.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.0.xsd=org/springframework/aop/config/spring-aop-3.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.1.xsd=org/springframework/aop/config/spring-aop-3.1.xsd
http\://www.springframework.org/schema/aop/spring-aop-3.2.xsd=org/springframework/aop/config/spring-aop-3.2.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.0.xsd=org/springframework/aop/config/spring-aop-4.0.xsd
http\://www.springframework.org/schema/aop/spring-aop-4.1.xsd=org/springframework/aop/config/spring-aop-4.1.xsd
http\://www.springframework.org/schema/aop/spring-aop.xsd=org/springframework/aop/config/spring-aop-4.1.xsd
我們看到一個xsd文件對應本地的一個路徑,我們打開org/springframework/aop/config/可以看到:

這就很明顯,Spring是把XSD文件放到本地了,再在spring.schemas里做了一個映射,優先從本地里加載XSD文件。
並且把spring舊版本的XSD文件也全放了。這樣可以防止升級了Spring版本,而配置文件里用的還是舊版本的XSD文件,然后斷網了,應用啟動不了。
注意我在spring.schemas中標紅的最后一行,說明我們在寫命名空間值對應的xsd文件位置時,可以不用寫版本號,它默認的是本地spring相關版本的對應xsd版本,我這里是4.1。
在xsi:schemaLocation中這樣寫:http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
六、總結
對於spring配置文件的頭,已經有了一個比較清楚的認識。在以后寫配置文件的時候不會再一股腦得全拷貝過來。首先看看需要哪些功能,再導入相應的命名空間。
最好是在寫命名空間值對應的xsd文件位置的時候,不加版本號,讓spring加載本地版本對應的xsd文件。
當然,也可以讓spring跳過對XML的校驗,具體方法:eclipse中,windows右鍵 ,去掉下圖紅色箭頭處的勾,就可以對本工作空間取消驗證xml文件:

或者針對某個單獨的xml文件右鍵,validate也行。
針對已經驗證過的文件,而且也沒做修改。我們可以取消對其自動驗證。對於新建的配置文件,我覺得最好還是不要取消驗證的好,畢竟我們在配置文件的時候,有驗證會讓我們今早發現錯誤。
補充,stackoverflow下的一個問題解答,很好的說明了 XML schema 命名空間如何與對應的class關聯起來的。也就是spring.handlers文件的作用。
http://stackoverflow.com/questions/11174286/spring-xml-namespaces-how-do-i-find-what-are-the-implementing-classes-behind-t
--總覺得自己講得不太清楚,還需要慢慢練習,多寫博客,鍛煉表達寫作能力,文中有表達不清或有誤的地方歡迎留言指正討論。
---------------------------------
2017-3-29 Gonjan
