2011-10-14 78 views
41

當我第一次開始學習Spring時,事情在applicationContext.xml文件中進行了配置。然後,當我開始專門閱讀更多春季版本的書籍時,他們都已經在單獨的XML文件(例如myapp-servlet-xml,myapp-security.xml,myapp-service.xml等)中完成了配置,在web.xml文件中配置contextConfigLocation。所以,舉例來說,我一直沿着下面的代碼有這個,因爲它是的contextConfigLocation:Spring XML文件配置層次結構幫助/說明

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value> 
     /WEB-INF/myapp-servlet.xml 
     /WEB-INF/myapp-data.xml 
    </param-value> 
</context-param> 

反正最近我遇到了一個配置問題(它在這裏StackOverflow上的樂於助人的人幫助我弄清楚),其是由於這種分離。這些書籍中的示例沒有applicationContext.xml文件,後來當我嘗試將自動掃描和註釋添加到應用程序時,這導致了問題。我試着將所有東西都移動到applicationContext.xml中,並廢除其他文件並解決了問題。沒有其他改變,我只是把所有東西放在applicationContext.xml中。

所以,這個以及其他人的評論讓我明白,即使你沒有創建applicationContext.xml,它仍然被使用,它是某種配置層次結構的頂層。我希望別人能向我解釋這是如何運作的,因爲我沒有在任何地方找到任何解釋。例如,如果我將某些上下文:component-scan標記放入applicationContext.xml下面的配置文件中,可能會導致某些類無法掃描。那種性質的東西。我不明白優先順序和必須去哪裏確定它應用範圍廣泛等等。如果任何人都可以清楚地解釋它或指出我解釋它的資源,我將非常感激,謝謝。希望我所問的是有道理的。

回答

83

對於名爲「applicationContext.xml」的文件沒有什麼特別之處,只不過它是Spring傾向於期望的名稱作爲其默認配置文件。使用名爲「dog.xml」,「cat.xml」和「alien.xml」的一個文件或多個文件將以完全相同的方式工作。您遇到的麻煩來自同時使用多個ApplicationContexts,而不是具有多個XML文件。我最近回答了一些由於不理解這些概念而導致問題的人的一些問題。看看這些答案,看你還有什麼問題:

Declaring Spring Bean in Parent Context vs Child Context

Spring-MVC: What are a "context" and "namespace"?

編輯:針對新的問題:

我有一個<context:component-scan base-package="com.myapp"/>標籤我的servlet.xml。

我猜這 「servlet.xml文件」 文件被命名爲喜歡foo-servlet.xml,其中在web.xml配置DispatcherServlet的被命名爲 「foo」 的,像

<servlet> 
    <servlet-name>foo</servlet-name> 
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
</servlet> 

按照慣例,當這DispatcherServlet啓動後,它將創建一個新的ApplicationContext,該文件由文件foo-servlet.xml配置,該文件源自servlet-name。現在,由於您將context:component-scan放在那裏,它將遞歸掃描給定的包併爲所有帶註釋的類創建bean。你給它的包,com.myapp,看起來就像是你的整個應用的基礎包,所以Spring將從你的應用中的所有創建bean的註釋類,包括數據訪問類,在這個ApplicationContext中關聯到DispatcherServlet的。通常,這個上下文應該只有視圖層的東西和bean,它們直接支持DispatcherServlet,所以這是一種錯誤的配置。

在我的data.xml文件中,我有數據源bean,就是這樣。沒有其他的豆,其他的一切都是自動裝配和註釋的。

大概這個「data.xml」文件就是你在contextConfigLocation context-param中列出的文件。假設你還添加了的ContextLoaderListener到你的web.xml,像

<listener> 
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
</listener> 

那麼該文件將被用來建立一個第二的ApplicationContext - 根上下文。這是這個聽衆所做的。請注意,它實際上構建了全部中列出的contextConfigLocation文件的上下文,並且如果您還在該列表中包含了「servlet.xml」,那麼您已經將該配置加載了兩次:這裏是在根上下文中以及在與DipatcherServlet相關的上下文。希望您現在瞭解XML配置文件和它們配置的ApplicationContext之間的區別。同一個XML文件可以很容易地用來配置兩個不同的上下文。這樣做是否正確是另一個問題。在這種特殊情況下,事實並非如此。

我描述這兩個上下文的順序實際上是向後的。我只是在描述你所做的事情。 ContextLoaderListener(作爲ServletContextListener)將始終在任何servlet啓動之前執行。這意味着根上下文首先被創建,而另一個上下文被創建。這是通過設計使得當DispatcherServlet創建它的上下文時,它可以將該上下文添加爲根上下文的子元素。我在其他帖子中描述了這種關係。其中最重要的影響是根環境中的bean可以通過DispatcherServlet的上下文獲得。這也適用於自動裝配關係。這很重要,因爲DispatcherServlet 只有在它的關聯上下文中查找它需要的bean,如控制器實例。但是,您的控制器顯然必須連接支持的豆子。因此,傳統上,控制器位於DispatcherServlet的上下文中,而支持bean位於根上下文中。

然後我嘗試添加@Transacational到我的服務bean,它不會持續。

爲使@Transactional正常工作,您必須將<tx:annotation-driven/>標記包含在註釋bean所在的ApplicationContext的配置中。訣竅是搞清楚「它住哪裏」的部分。小孩中的豆可以在父上下文中覆蓋bean。因此 - 我只是在這裏猜測 - 如果您將所有bean加載到DispatcherServlet上下文中(如上所述),但將<tx:annotation-driven/>置於根上下文中,則可能在根上下文中具有正確事務性的bean,但它不是因爲副本與父/子層次結構中的servlet「更接近」,並且它所處的上下文未獲得配置,所以使用了該配置。

當我改變servlet上下文:組件掃描標籤以com.myapp.web,而不是點,然後添加一個背景:組件掃描標籤data.xml文件的,一切正常。

它仍然一定程度上取決於你是包括在其中的ApplicationContexts,但最起碼​​我可以說,通過這樣做,你刪除了很多從DispatcherServlet的上下文這是造成問題的咖啡豆到底哪個配置文件。特別是,在根上下文中正確配置的@Transactional bean將不再被子上下文中的bean所影響,並且會被注入到控制器中,因此您的持久性內容將會起作用。

所以......最重要的是你有兩個相關的ApplicationContexts。你必須意識到這一事實,並保持控制哪些豆在哪種情況下發生。

這是否涵蓋所有內容?

+0

非常感謝您的幫助和鏈接。鏈接提供了我正在尋找的一些澄清。我確實有一個問題。我在我的servlet.xml中有一個標記。在我的data.xml文件中,我有數據源bean,就是這樣。沒有其他的豆,其他的一切都是自動裝配和註釋的。然後,我嘗試添加@Transacational到我的服務bean,它不會持久。當我將servlet上下文:component-scan標記改爲指向com.myapp.web,然後將上下文:component-scan標記添加到data.xml文件時,一切都奏效了。 – cardician

+0

所以我的問題是,你能澄清這是爲什麼嗎?我有一個調度程序servlet,它查看servlet.xml,因此不是根上下文。嗯......我想我還是不完全明白事情是如何融合在一起的。非常感謝。 – cardician

+0

非常感謝你!我認爲你真的幫助清理了我讀過的書籍和Spring Docs中看不到的東西。我確實把我的serlvet.xml文件放到contextConfigLocation列表中,正如你所說的那樣,導致了兩個上下文。這可能不是我唯一的問題,但絕對是其中之一。現在你的解釋我應該能夠通過並確保一切正確配置。另外我感謝你列舉Spring如何加載文件。我確實認爲一切都更加清晰。再次感謝。 – cardician