两个相同的方法加上@spring getbean 方法为什么会冲突

下次自动登录
现在的位置:
& 综合 & 正文
关于spring中处理相同id的bean的问题
根据DefaultListableBeanFactory这个bean的实现:
private boolean allowBeanDefinitionOverriding = true;
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException ...{
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "Bean definition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) ...{
((AbstractBeanDefinition) beanDefinition).validate();
catch (BeanDefinitionValidationException ex) ...{
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition with name failed", ex);
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) ...{
if (!this.allowBeanDefinitionOverriding) ...{
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': there's already [" + oldBeanDefinition + "] bound");
if (logger.isInfoEnabled()) ...{
("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
this.beanDefinitionNames.add(beanName);
this.beanDefinitionMap.put(beanName, beanDefinition);
// Remove corresponding bean from singleton cache, if any.
// Shouldn't usually be necessary, rather just meant for overriding
// a context's default beans (e.g. the default StaticMessageSource
// in a StaticApplicationContext).
removeSingleton(beanName);
可以看出spring缺省是可以让两个相同名字的bean注册,只是后注册的把前一个给替换了而已。这点与picocontainer是不一样的,真是令人奇怪的习惯啊。
&&&&推荐文章:
【上篇】【下篇】14799人阅读
&& 当我们的web应用做成一个大项目之后,里面有很多的bean配置,如果两个bean的配置id是一样的而且实现类也是一样的,例如有下面两份xml的配置文档:
beancontext1.xml
&?xml version=&1.0& encoding=&UTF-8&?&
&!DOCTYPE beans PUBLIC &-//SPRING//DTD BEAN//EN& &/spring-beans.dtd&&
&bean id=&testbean& class=&com.koubei.samebeannameconfict.Bean&&
&property name=&name& value=&beancontext1& /&
beancontext2.xml
&?xml version=&1.0& encoding=&UTF-8&?&
&!DOCTYPE beans PUBLIC &-//SPRING//DTD BEAN//EN& &/spring-beans.dtd&&
&bean id=&testbean& class=&com.koubei.samebeannameconfict.Bean&&
&property name=&name& value=&beancontext2& /&
&/beans&&&
当spring容器初始化时候同时加载这两份配置文件到当前的上下文的时候,代码如下:
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
new String[] {
&com/koubei/samebeannameconfict/beancontext1.xml&,
&com/koubei/samebeannameconfict/beancontext2.xml& });
//context.setAllowBeanDefinitionOverriding(false);
//context.refresh();
Bean bean = (Bean) context.getBean(&testbean&);
System.out.println(bean.getName());
&执行这个程序你会看见控制台上打印的结果是:
beancontext2
显然,beancontext2.xml的bean的配置覆盖了 beancontext1.xml中bean的配置,而且在spring初始化上下文的过程中这个过程是静悄悄的执行的,连一点警告都没有。这样如果你的项目中定义了两个id同名的bean,并且,他们的实现方式又是不一样的,这样在后期在项目中执行的逻辑看起来就会非常诡异,而且,如果有大量配置spring配置文件的话,排查问题就会非常麻烦。
解决问题:
& 那么,我们如何来解决这个问题吗?靠程序员自律?绝对不定义重复名称的bean?我觉得这个是不靠谱的,只有通过在程序中引入一种交错机制才能解决这个问题。
&& 首先,我们将上面那段程序的log4j日志打开,看看在spring在初始化的时候面对有两个同名的bean是怎么处理的。
- INFO - Refreshing : 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= abstract= lazyInit= autowireMode=0; dependencyCheck=0; autowireCandidate= primary= factoryBeanName= factoryMethodName= initMethodName= destroyMethodName= defined in class path resource [com/koubei/samebeannameconfict/beancontext1.xml]]
with [Generic bean: class [com.koubei.samebeannameconfict.Bean]; scope= abstract= lazyInit= autowireMode=0; dependencyCheck=0; autowireCandidate= primary= factoryBeanName= factoryMethodName= initMethodName= destroyMethodName=
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]:
- DEBUG - 1 beans defined in : 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 : 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'
以上日志中标红的是关键,spring在处理有重名的bean的定义的时候原来是使用的覆盖(override)的方式。我们来看看它是如何覆盖的
在org.springframework.beans.factory.support.DefaultListableBeanFactory 这个类中有这样一段代码:
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition
.getResourceDescription(), beanName,
&Cannot register bean definition [&
+ beanDefinition + &] for bean '&
+ beanName + &': There is already [&
+ oldBeanDefinition + &] bound.&);
if (this.logger.isInfoEnabled()) {
this.logger
.info(&Overriding bean definition for bean '&
+ beanName + &': replacing [&
+ oldBeanDefinition + &] with [&
+ beanDefinition + &]&);
this.beanDefinitionNames.add(beanName);
this.frozenBeanDefinitionNames =
this.beanDefinitionMap.put(beanName, beanDefinition);
resetBeanDefinition(beanName);
&&&& spring ioc容器在加载bean的过程中会去判断beanName 是否有重复,如果发现重复的话在根据allowBeanDefinitionOverriding 这个成员变量,如果是false的话则抛出BeanDefinitionStoreException 这个异常,如果为true的话就会覆盖这个bean的定义(默认为true)。
所以,解决这个问题的办法就比较简单了,只要将这个allowBeanDefinitionOverriding值在spring初始化的时候设置为false就行了。
我把解决这个问题的环境放到,web工程中来:
在web工程中加载spring容器会通过:
&listener&
&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&
&/listener&
这个listener来完成的,在这个listener中会构造 org.springframework.web.context.ContextLoader 这个构造器来加载bean
所以,只要扩展 ContextLoader 和ContextLoaderListener这两个类就行了,代码如下:
KoubeiContextLoader:
import org.springframework.web.context.ConfigurableWebApplicationC
import org.springframework.web.context.ContextL
import org.springframework.web.context.support.XmlWebApplicationC
* @author 百岁(莫正华 )
* @version 1.0
public class KoubeiContextLoader extends ContextLoader {
protected void customizeContext(ServletContext servletContext,
ConfigurableWebApplicationContext applicationContext) {
XmlWebApplicationContext context = (XmlWebApplicationContext) applicationC
context.setAllowBeanDefinitionOverriding(false);
KoubeiContextLoaderListener:
* @author 百岁(莫正华 )
* @version 1.0
public class KoubeiContextLoaderListener extends ContextLoaderListener {
protected ContextLoader createContextLoader() {
return new KoubeiContextLoader();
最后修改wen-inf 下web.xml 文件,修改listener的配置,如下:
&listener&
&listener-class&com.koubei.kac.springcontext.KoubeiContextLoaderListener&/listener-class&
&/listener&
设置完这些就ok了,这样你项目中如果在两份被加载的xml文件中如果再出现名字相同的bean的话,spring在加载过程中就会无情的抛出异常,当你去除掉这个异常之后,就能重新出发了。yeah!!!!
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:79893次
积分:1030
积分:1030
排名:千里之外
原创:25篇
评论:44条
(1)(1)(3)(4)(1)(1)(1)(2)(2)(1)(3)(1)(1)(1)(1)(2)spring巧用继承解决bean的id相同的问题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
spring巧用继承解决bean的id相同的问题
上传于||文档简介
&&spring巧用继承解决bean的id相同的问题
阅读已结束,如果下载本文需要使用1下载券
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩6页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢

我要回帖

更多关于 spring bean id 冲突 的文章

 

随机推荐