對於名爲「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。你必須意識到這一事實,並保持控制哪些豆在哪種情況下發生。
這是否涵蓋所有內容?
非常感謝您的幫助和鏈接。鏈接提供了我正在尋找的一些澄清。我確實有一個問題。我在我的servlet.xml中有一個標記。在我的data.xml文件中,我有數據源bean,就是這樣。沒有其他的豆,其他的一切都是自動裝配和註釋的。然後,我嘗試添加@Transacational到我的服務bean,它不會持久。當我將servlet上下文:component-scan標記改爲指向com.myapp.web,然後將上下文:component-scan標記添加到data.xml文件時,一切都奏效了。 –
cardician
所以我的問題是,你能澄清這是爲什麼嗎?我有一個調度程序servlet,它查看servlet.xml,因此不是根上下文。嗯......我想我還是不完全明白事情是如何融合在一起的。非常感謝。 – cardician
非常感謝你!我認爲你真的幫助清理了我讀過的書籍和Spring Docs中看不到的東西。我確實把我的serlvet.xml文件放到contextConfigLocation列表中,正如你所說的那樣,導致了兩個上下文。這可能不是我唯一的問題,但絕對是其中之一。現在你的解釋我應該能夠通過並確保一切正確配置。另外我感謝你列舉Spring如何加載文件。我確實認爲一切都更加清晰。再次感謝。 – cardician