事情的起因是,除錯過程中,發現有一處事務不起效。後來發現是spring配置檔案被改動。
於是對各個spring配置檔案進行了分析。
在這裡先給出四個配置檔案的部分內容,著重關注標紅的部分: 省略
class="org.springframework.beans.factory.config.propertyplaceholderconfigurer">
classpath:constants.properties
spring-servlet.xml:
class="org.springframework.beans.factory.config.propertyplaceholderconfigurer">
classpath:constants.properties
classpath:conf/installation.properties
web.xml:
contextconfiglocation
classpath:springbeans/*-beans.xml
classpath:springmvc-servlet.xml
springmvc
org.springframework.web.servlet.dispatcherservlet
contextconfiglocation
classpath*:springmvc-servlet.xml
spring-servlet.xml中自動掃瞄action、service、dao、api、impl、servlet、web、ldap、ref等包下的bean,設定為cglib**。配置***、配置資料轉換功能,配置一些bean。配置propertyplaceholderconfigurer。
web.xml中配置過濾器、servlet、listener等
讓我們來看下web.xml中標紅的配置:
contextconfiglocation
classpath:springbeans/*-beans.xml
classpath:springmvc-servlet.xml
web應用程式需要共享的一些元件。
而如下配置:
springmvc
org.springframework.web.servlet.dispatcherservlet
contextconfiglocation
classpath*:springmvc-servlet.xml
這個是用來處理所有
servlet
的,沒有它就無法通過請求位址來呼叫相應的
controller
。如果不指定,則會按照注釋中所描述地那樣自動載入
"工程名
-servlet.xml"
配置檔案。在這裡我們通過
init-param
指定為spring-servlet.xml檔案。
sping+springmvc
的框架中,
ioc容器的載入過程:
基本上web容器(如
tomcat)
先載入contextloaderlistener
(載入),然後生成乙個
ioc容器。
然後再例項化
dispatchservlet
時候會載入對應的配置檔案(spring-servlet.xml),再次生成
controller
相關的ioc
容器。
對於作用範圍而言,在
dispatcherservlet
中可以引用由
contextloaderlistener
所建立的
,而反過來不行。
於是,如果對於這兩份配置沒有很好的認識,不注重物件初始化的分類,尤其是使用
這樣的包掃瞄形式統一初始化,很容易造成滿足條件的物件被初始化兩次。不同的配置檔案其作用是不一樣的,不要將所有的初始化操作都放到乙個配置檔案中,更不要重複配置。重複載入配置檔案,導致
bean
被上述兩個
ioc容器重複載入,生成兩份例項,不僅會浪費資源,還會導致莫名其妙的故障。如果存在定時任務,則定時任務也會被執行兩次。
根本原因:由此可見spring-servlet.xml檔案被載入了兩次,spring 容器和spring mvc容器分別都初始化了spring-servlet.xml中定義的例項。
解決方案:
1.去掉context-param中配置的springmvc-servlet.xml,使springmvc-servlet.xml只被掃瞄一遍。
spring mvc的配置檔案spring-servlet.xml嚴格限制只初始化controller層例項;
修改配置後,報錯illegalargumentexception: could not resolve placeholder……
回到一開始導致問題暴露的那個修改,當時是把spring-servlet.xml中的刪除了,這個配置是設定為cglib**。那麼生成的兩份例項中,其中dispatcherservlet建立的一部分例項沒有用cglib**,覆蓋了contextloaderlistener
所建立的使用了cglib**的例項,導致事務無法生效。
將spring包日誌的debug開啟,啟動專案至正常執行後,在日誌中搜尋「creating cglib proxy」,原本cglib**兩次時搜尋結果為738,錯誤修改刪除cglib**配置後,搜尋結果為369,為原來的一半,符合之前的分析。正確修改各個配置檔案後,再次搜尋結果為284(又去掉了spring-servlet.xml檔案中的cglib**配置,所以**個數減少)。
spring 註解掃瞄bean配置
spring公共配置 spring 會自動掃瞄com.zghw下的spring註解 常用註解 定義bean的註解 controller controller bean的名稱 定義控制層bean,如action service service bean的名稱 定義業務層bean repository ...
Spring 配置 (包含掃瞄Aspect)
這個標籤 是 如果掃瞄到有 component controller service等這些註解的類,則把這些類註冊為bean。是不掃瞄 aspect註解的。所以我們需要在子標籤新增 expression org.aspectj.lang.annotation.aspect use ult filte...
spring掃瞄配置檔案
spring配置檔案對應的是父容器,springmvc配置檔案產生的是子容器,前者一般配置資料來源,事務,註解等,當然還可以進一步將一些配置細化到其他xml中 後者一般配置控制層相關的,如靜態資源,視 析器等。系統啟動的時候,先初始化父容器,然後初始化子容器。這裡會涉及乙個問題,如果配置元件掃瞄時都...