国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
spring bean id重復(fù)覆蓋的問(wèn)題解決

問(wèn)題:

   當(dāng)我們的web應(yīng)用做成一個(gè)大項(xiàng)目之后,里面有很多的bean配置,如果兩個(gè)bean的配置id是一樣的而且實(shí)現(xiàn)類也是一樣的,例如有下面兩份xml的配置文檔:

beancontext1.xml

 

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "/spring-beans.dtd">  
  3. <beans>  
  4.     <bean id="testbean" class="com.koubei.samebeannameconfict.Bean">  
  5.         <property name="name" value="beancontext1" />  
  6.     </bean>  
  7. </beans>  

 

beancontext2.xml

 

  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "/spring-beans.dtd">  
  3. <beans>  
  4.     <bean id="testbean" class="com.koubei.samebeannameconfict.Bean">  
  5.         <property name="name" value="beancontext2" />  
  6.     </bean>  
  7. </beans>  
  

 

當(dāng)spring容器初始化時(shí)候同時(shí)加載這兩份配置文件到當(dāng)前的上下文的時(shí)候,代碼如下:

 

  1. public static void main(String[] args) {  
  2.   
  3.         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(  
  4.                 new String[] {  
  5.                         "com/koubei/samebeannameconfict/beancontext1.xml",  
  6.                         "com/koubei/samebeannameconfict/beancontext2.xml" });  
  7.   
  8.         //context.setAllowBeanDefinitionOverriding(false);  
  9.         //context.refresh();  
  10.         Bean bean = (Bean) context.getBean("testbean");  
  11.         System.out.println(bean.getName());  
  12.     }  

 

 執(zhí)行這個(gè)程序你會(huì)看見控制臺(tái)上打印的結(jié)果是:

beancontext2

顯然,beancontext2.xml的bean的配置覆蓋了 beancontext1.xml中bean的配置,而且在spring初始化上下文的過(guò)程中這個(gè)過(guò)程是靜悄悄的執(zhí)行的,連一點(diǎn)警告都沒有。這樣如果你的項(xiàng)目中定義了兩個(gè)id同名的bean,并且,他們的實(shí)現(xiàn)方式又是不一樣的,這樣在后期在項(xiàng)目中執(zhí)行的邏輯看起來(lái)就會(huì)非常詭異,而且,如果有大量配置spring配置文件的話,排查問(wèn)題就會(huì)非常麻煩。

 

解決問(wèn)題:

  那么,我們?nèi)绾蝸?lái)解決這個(gè)問(wèn)題嗎?靠程序員自律?絕對(duì)不定義重復(fù)名稱的bean?我覺得這個(gè)是不靠譜的,只有通過(guò)在程序中引入一種交錯(cuò)機(jī)制才能解決這個(gè)問(wèn)題。

   首先,我們將上面那段程序的log4j日志打開,看看在spring在初始化的時(shí)候面對(duì)有兩個(gè)同名的bean是怎么處理的。

 

- INFO - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@aa9835: display name [org.springframework.context.support.ClassPathXmlApplicationContext@aa9835]; startup date [Sat Jun 19 18:23:30 CST 2010]; root of context hierarchy
- INFO - Loading XML bean definitions from class path resource [com/koubei/samebeannameconfict/beancontext1.xml]
- DEBUG - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
- DEBUG - Found beans DTD [file:///spring-beans.dtd] in classpath: spring-beans.dtd
- DEBUG - Loading bean definitions
- DEBUG - Loaded 1 bean definitions from location pattern [com/koubei/samebeannameconfict/beancontext1.xml]
- INFO - Loading XML bean definitions from class path resource [com/koubei/samebeannameconfict/beancontext2.xml]
- DEBUG - Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
- DEBUG - Found beans DTD [file:///spring-beans.dtd] in classpath: spring-beans.dtd
- DEBUG - Loading bean definitions
- INFO - Overriding bean definition for bean 'testbean': replacing [Generic bean: class[com.koubei.samebeannameconfict.Bean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [com/koubei/samebeannameconfict/beancontext1.xml]] with [Generic bean: class [com.koubei.samebeannameconfict.Bean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [com/koubei/samebeannameconfict/beancontext2.xml]]
- DEBUG - Loaded 0 bean definitions from location pattern [com/koubei/samebeannameconfict/beancontext2.xml]
- INFO - Bean factory for application context [org.springframework.context.support.ClassPathXmlApplicationContext@aa9835]:org.springframework.beans.factory.support.DefaultListableBeanFactory@1662dc8
- DEBUG - 1 beans defined in org.springframework.context.support.ClassPathXmlApplicationContext@aa9835: display name [org.springframework.context.support.ClassPathXmlApplicationContext@aa9835]; startup date [Sat Jun 19 18:23:30 CST 2010]; root of context hierarchy
- DEBUG - Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource@1cb25f1]
- DEBUG - Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicationEventMulticaster@503429]
- INFO - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1662dc8: defining beans [testbean]; root of factory hierarchy
- DEBUG - Creating shared instance of singleton bean 'testbean'
- DEBUG - Creating instance of bean 'testbean'
- DEBUG - Eagerly caching bean 'testbean' to allow for resolving potential circular references
- DEBUG - Finished creating instance of bean 'testbean'
- DEBUG - Returning cached instance of singleton bean 'testbean'

 

以上日志中標(biāo)紅的是關(guān)鍵,spring在處理有重名的bean的定義的時(shí)候原來(lái)是使用的覆蓋(override)的方式。我們來(lái)看看它是如何覆蓋的

在org.springframework.beans.factory.support.DefaultListableBeanFactory 這個(gè)類中有這樣一段代碼:

 

  1. synchronized (this.beanDefinitionMap) {  
  2.     Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);  
  3.     if (oldBeanDefinition != null) {  
  4.         if (!this.allowBeanDefinitionOverriding) {  
  5.             throw new BeanDefinitionStoreException(beanDefinition  
  6.                     .getResourceDescription(), beanName,  
  7.                     "Cannot register bean definition ["  
  8.                             + beanDefinition + "] for bean '"  
  9.                             + beanName + "': There is already ["  
  10.                             + oldBeanDefinition + "] bound.");  
  11.         } else {  
  12.             if (this.logger.isInfoEnabled()) {  
  13.                 this.logger  
  14.                         .info("Overriding bean definition for bean '"  
  15.                                 + beanName + "': replacing ["  
  16.                                 + oldBeanDefinition + "] with ["  
  17.                                 + beanDefinition + "]");  
  18.             }  
  19.         }  
  20.     } else {  
  21.         this.beanDefinitionNames.add(beanName);  
  22.         this.frozenBeanDefinitionNames = null;  
  23.     }  
  24.     this.beanDefinitionMap.put(beanName, beanDefinition);  
  25.     resetBeanDefinition(beanName);  
  26. }  



 

     spring ioc容器在加載bean的過(guò)程中會(huì)去判斷beanName 是否有重復(fù),如果發(fā)現(xiàn)重復(fù)的話在根據(jù)allowBeanDefinitionOverriding 這個(gè)成員變量,如果是true的話則拋出BeanDefinitionStoreException 這個(gè)異常,如果為false的話就會(huì)覆蓋這個(gè)bean的定義。

所以,解決這個(gè)問(wèn)題的辦法就比較簡(jiǎn)單了,只要將這個(gè)allowBeanDefinitionOverriding值在spring初始化的時(shí)候設(shè)置為false就行了。

我把解決這個(gè)問(wèn)題的環(huán)境放到,web工程中來(lái):

在web工程中加載spring容器會(huì)通過(guò):

 

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

 

這個(gè)listener來(lái)完成的,在這個(gè)listener中會(huì)構(gòu)造 org.springframework.web.context.ContextLoader 這個(gè)構(gòu)造器來(lái)加載bean

所以,只要擴(kuò)展 ContextLoader 和ContextLoaderListener這兩個(gè)類就行了,代碼如下:

KoubeiContextLoader:

 

  1. import org.springframework.web.context.ConfigurableWebApplicationContext;  
  2. import org.springframework.web.context.ContextLoader;  
  3. import org.springframework.web.context.support.XmlWebApplicationContext;  
  4.   
  5. /** 
  6.  *  
  7.  *  
  8.  * @version 1.0 2010-6-19 
  9.  */  
  10. public class KoubeiContextLoader extends ContextLoader {  
  11.   
  12.     @Override  
  13.     protected void customizeContext(ServletContext servletContext,  
  14.             ConfigurableWebApplicationContext applicationContext) {  
  15.         XmlWebApplicationContext context = (XmlWebApplicationContext) applicationContext;  
  16.         context.setAllowBeanDefinitionOverriding(false);  
  17.     }  
  18.   
  19. }  

 

KoubeiContextLoaderListener:

 

  1. /** 
  2.  *  
  3.  *  
  4.  * @author 百歲(莫正華 baisui@taobao.com) 
  5.  * @version 1.0 2010-6-19 
  6.  */  
  7. public class KoubeiContextLoaderListener extends ContextLoaderListener {  
  8.   
  9.     @Override  
  10.     protected ContextLoader createContextLoader() {  
  11.         return new KoubeiContextLoader();  
  12.     }  
  13.   
  14. }  

 

最后修改wen-inf 下web.xml 文件,修改listener的配置,如下:

 

  1. <listener>  
  2.         <listener-class>com.koubei.kac.springcontext.KoubeiContextLoaderListener</listener-class>  
  3. </listener>  

 

設(shè)置完這些就ok了,這樣你項(xiàng)目中如果在兩份被加載的xml文件中如果再出現(xiàn)名字相同的bean的話,spring在加載過(guò)程中就會(huì)無(wú)情的拋出異常,當(dāng)你去除掉這個(gè)異常之后,就能重新出發(fā)了。yeah?。。?!

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
spring4.0之二:@Configuration的使用
基于Maven的Spring + Spring MVC + Mybatis的環(huán)境搭建 | AmazingHarry
使用 Spring 2 Portlet MVC 框架構(gòu)建 Portlet 應(yīng)用
spring面試題
SpringFramework(11) (完)
Spring Web 中模塊化配置文件的加載
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服