spring配置錯誤重複掃瞄導致事務失效的問題解決

2021-09-26 12:02:04 字數 3057 閱讀 8696

事情的起因是,除錯過程中,發現有一處事務不起效。後來發現是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中 後者一般配置控制層相關的,如靜態資源,視 析器等。系統啟動的時候,先初始化父容器,然後初始化子容器。這裡會涉及乙個問題,如果配置元件掃瞄時都...