使用監(jiān)聽器對Spring bean id進行唯一校驗過程解析
背景
項目中用到了多數據源,不同的數據源根據業(yè)務不同配置在不同的工程中,由maven來統一聚合。但是前幾天在開發(fā)過程中突然發(fā)現項目前臺工程的事務配置不起作用了,在之前明明測試過事務功能,當時是生效的。
然后檢查了一下配置文件中事務部分的配置,發(fā)現沒什么改動。為了排除其它因素的干擾,采用了單元測試重新測試了一次,結果發(fā)現當前數據源事務正常。根據這個分析可能是當前的事務配置被其它配置干擾了,仔細檢查了一下后發(fā)現罪魁禍首是另外的一個數據源事務配置(在另外的一個配置文件中)的bean id名稱和當前的事務配置bean id重復了。
我們都知道,Spring會對同一份配置文件中的bean進行校驗,也就是說在同一份配置文件中不允許出現相同的bean定義,會提示報錯。但是Spring IOC容器在加載時并不會顯示對不同配置文件中重復的bean id進行報錯提示,當遇到有重復的bean定義時,Spring采取的策略是把后面加載的配置覆蓋前面加載的配置,沒有任何警告和提示。
這樣很容易造成一個問題是當我們團隊進行開發(fā)時可能會不小心覆蓋別人定義的bean,導致系統出現不可預知的錯誤和異常。
怎么解決這個問題呢?我們可以配置監(jiān)聽器,在Spring容器啟動時對重復的bean進行校驗,如果有重復的bean,則報錯提示。
因為Spring IOC容器啟動加載時會檢查bean定義是否有重復,如果有重復則會根據AbstractRefreshableApplicationContext類中的allowBeanDefinitionOverriding屬性值進行判斷,如果值為true,則把后加載的bean覆蓋前面加載的bean定義,如果為false則拋出BeanDefinitionStoreException異常。
所以,解決這個問題的辦法就比較簡單了,只要將這個allowBeanDefinitionOverriding值在spring初始化的時候設置為false就行了。具體步驟如下:
1.自定義一個ContextLoader
/** * ClassName:MyContextLoader <br/> * Function: 自定義ContextLoader. <br/> * Date: 2013-1-18 下午03:53:16 <br/> * @author chenzhou * @version * @since JDK 1.6 */ public class MyContextLoader extends ContextLoader { /** * 設置allowBeanDefinitionOverriding屬性為false,spring ioc容器在加載bean的過程中會去判斷beanName 是否有重復,. <br/> * 如果發(fā)現重復的話再根據allowBeanDefinitionOverriding 這個成員變量,. <br/> * 如果是false的話則拋出BeanDefinitionStoreException 這個異常,如果為true的話就會覆蓋這個bean的定義. <br/> * @see org.springframework.web.context.ContextLoader#customizeContext(javax.servlet.ServletContext, * org.springframework.web.context.ConfigurableWebApplicationContext) */ @Override protected void customizeContext(ServletContext servletContext, ConfigurableWebApplicationContext applicationContext){ super.customizeContext(servletContext, applicationContext); XmlWebApplicationContext context = (XmlWebApplicationContext) applicationContext; //設置allowBeanDefinitionOverriding屬性為false context.setAllowBeanDefinitionOverriding(false); } }
2.自定義一個ContextLoaderListener
/** * ClassName:MyContextLoaderListener <br/> * Function: 自定義ContextLoaderListener. <br/> * Date: 2013-1-18 下午04:12:00 <br/> * @author chenzhou * @version * @since JDK 1.6 */ public class MyContextLoaderListener extends ContextLoaderListener { @Override protected ContextLoader createContextLoader(){ return new MyContextLoader(); } }
3.修改web.xml文件的監(jiān)聽器配置
<!-- 自定義的ContextLoaderListener --> <listener> <listener-class>com.chenzhou.examples.erm.util.listener.MyContextLoaderListener</listener-class> </listener>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- spring中bean id相同引發(fā)故障的分析與解決
- Spring實戰(zhàn)之容器中的工程Bean用法示例
- Spring實戰(zhàn)之抽象Bean和子Bean定義與用法示例
- Spring實戰(zhàn)之調用實例工廠方法創(chuàng)建Bean操作示例
- Spring實戰(zhàn)之使用靜態(tài)工廠方法創(chuàng)建Bean操作示例
- Spring如何使用注解的方式創(chuàng)建bean
- Spring實戰(zhàn)之注入嵌套Bean操作示例
- Java類獲取Spring中bean的5種方式
- Spring的自動裝配Bean的三種方式
- Spring實戰(zhàn)之獲得Bean本身的id操作示例
相關文章
SpringBoot2 整合FreeMarker實現頁面靜態(tài)化示例詳解
這篇文章主要介紹了SpringBoot2 整合FreeMarker實現頁面靜態(tài)化示例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07Java 可視化垃圾回收_動力節(jié)點Java學院整理
Ben Evans是一名資深培訓師兼顧問,他在演講可視化垃圾回收中從基礎談起討論了垃圾回收。以下是對其演講的簡短總結。感興趣的朋友一起學習吧2017-05-05Springboot項目編譯后未能加載靜態(tài)資源文件的問題
這篇文章主要介紹了Springboot項目編譯后未能加載靜態(tài)資源文件的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08