`
mozhenghua
  • 浏览: 324424 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

spring bean id重复覆盖的问题解决

 
阅读更多

问题:

当我们的web应用做成一个大项目之后,里面有很多的bean配置,如果两个bean的配置id是一样的而且实现类也是一样的,例如有下面两份xml的配置文档:

beancontext1.xml

beancontext2.xml

当spring容器初始化时候同时加载这两份配置文件到当前的上下文的时候,代码如下:

执行这个程序你会看见控制台上打印的结果是:

beancontext2

显然,beancontext2.xml的bean的配置覆盖了 beancontext1.xml中bean的配置,而且在spring初始化上下文的过程中这个过程是静悄悄的执行的,连一点警告都没有。这样如果你的项目中定义了两个id同名的bean,并且,他们的实现方式又是不一样的,这样在后期在项目中执行的逻辑看起来就会非常诡异,而且,如果有大量配置spring配置文件的话,排查问题就会非常麻烦。

解决问题:

那么,我们如何来解决这个问题吗?靠程序员自律?绝对不定义重复名称的bean?我觉得这个是不靠谱的,只有通过在程序中引入一种交错机制才能解决这个问题。

首先,我们将上面那段程序的log4j日志打开,看看在spring在初始化的时候面对有两个同名的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'

以上日志中标红的是关键,spring在处理有重名的bean的定义的时候原来是使用的覆盖(override)的方式。我们来看看它是如何覆盖的

在org.springframework.beans.factory.support.DefaultListableBeanFactory 这个类中有这样一段代码:

spring ioc容器在加载bean的过程中会去判断beanName 是否有重复,如果发现重复的话在根据allowBeanDefinitionOverriding 这个成员变量,如果是true的话则抛出BeanDefinitionStoreException 这个异常,如果为false的话就会覆盖这个bean的定义。

所以,解决这个问题的办法就比较简单了,只要将这个allowBeanDefinitionOverriding值在spring初始化的时候设置为false就行了。

我把解决这个问题的环境放到,web工程中来:

在web工程中加载spring容器会通过:

这个listener来完成的,在这个listener中会构造 org.springframework.web.context.ContextLoader 这个构造器来加载bean

所以,只要扩展 ContextLoader 和ContextLoaderListener这两个类就行了,代码如下:

KoubeiContextLoader:

KoubeiContextLoaderListener:

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

设置完这些就ok了,这样你项目中如果在两份被加载的xml文件中如果再出现名字相同的bean的话,spring在加载过程中就会无情的抛出异常,当你去除掉这个异常之后,就能重新出发了。yeah!!!!

分享到:
评论
1 楼 Not_Lost_Yesterday 2016-11-09  
你的 demo 似乎写错了,我理解了你的意思 ,spring 确实有个allowBeanDefinitionOverriding参数,它为false当name相同的bean 他会覆盖的(不管实现类是否相同),但是它的值为true时 就会抛出异常。

spring 3 里面 他的默认值就是true。

相关推荐

    spring中bean id相同引发故障的分析与解决

    本文将深入探讨Spring中bean id重复的问题,以及如何解决这个问题。 首先,我们要明确的是,Spring容器加载Bean时,如果发现有相同的`id`,会以最后一个被加载的Bean为准,即后面的Bean会覆盖前面的Bean。这在上述...

    使用监听器对Spring bean id进行唯一校验过程解析

    使用监听器对Spring bean id进行唯一校验是解决bean id重复问题的有效方法。同时,我们也可以使用其他方法来实现bean id的唯一性校验,例如使用BeanFactoryPostProcessor来实现bean id的唯一性校验。

    通过实例解析spring bean之间的关系

    在Spring框架中,Bean之间的关系是构建复杂应用的重要组成部分。本文将通过实例解析Spring Bean之间的两种主要关系:继承和依赖。 一、Bean的继承关系 Bean的继承关系体现在配置文件中,允许一个Bean(子Bean)...

    Java的Spring框架中bean的继承与内部bean的注入

    在Java的Spring框架中,Bean的继承和内部Bean的注入是两种重要的概念,它们帮助开发者构建灵活、可扩展的应用程序。Spring作为Java的SSH(Struts、Spring、Hibernate)三大Web开发框架之一,提供了丰富的功能,包括...

    Spring容器 .ppt

    Spring支持Bean定义的继承,子Bean定义可以从父Bean定义中继承属性,然后覆盖或添加自己的配置。这有助于减少重复代码并提高可维护性。 7. **容器扩展点** Spring提供了多种扩展点,如AOP代理、事件发布、国际化...

    spring学习小结

    <bean id="bean2" class="com.bjsxt.spring.Bean2" parent="AbstractBean"> <!-- 覆盖或添加属性 --> </bean> ``` 6. **依赖注入 (Dependency Injection, DI)** Spring 通过DI管理bean之间的依赖关系。有三种...

    自己总结的Spring实用资料

    Spring框架是Java应用程序开发中的一个核心工具,它主要解决了企业应用开发的复杂性问题,尤其在依赖管理和控制反转(IoC)方面表现出色。本文将详细介绍Spring的核心概念、配置过程以及一些实用技巧。 1. **Spring...

    Spring XML配置的12个技巧

    - **技巧说明**:Spring允许Bean继承另一个Bean的定义,从而减少了重复代码。例如,可以创建一个抽象Bean,然后其他具体的Bean继承这个抽象Bean。 - **示例代码**: ```xml <bean id="abstractService" ...

    Spring中XML配置文件的十二个最佳方法[借鉴].pdf

    在XML配置中,bean ID应遵循Java字段命名规则,例如,对于名为`OrderServiceDAO`的类,bean ID可以是`orderServiceDAO`。大型项目中,可以添加包名作为前缀,以增加唯一性。 3. 使用简洁形式 简洁形式是Spring XML...

    spring-reference

    - Spring支持抽象Bean定义,允许子Bean继承父Bean的配置,减少了重复配置。 - **Interacting with the BeanFactory** - Spring提供了获取FactoryBean本身而不是其产品的API。 - **Customizing Beans with ...

    Spring框架测试.zip

    使用JUnit和Hamcrest,我们可以编写针对Spring Bean、AOP切面、数据访问层(如JDBC、Hibernate或MyBatis)以及服务层的测试。通过模拟(Mocking)和存根(Stubbing)外部依赖,我们可以确保测试的隔离性,只关注被测...

    spring与mybatis三种整合方法

    - 在Spring配置中,创建`SqlSessionFactory` bean,然后创建`SqlSessionTemplate` bean,设置`SqlSessionFactory`作为依赖。 - DAO接口和实现类与第一种方式类似,但需要使用`SqlSessionTemplate`来执行SQL语句,...

    Spring从入门到精通05

    以下将基于这个主题展开详细介绍,覆盖Spring的基础概念、核心功能以及具体应用场景等。 ### Spring框架概述 Spring框架是由Rod Johnson创建的一个开源框架,最初是为了简化企业级应用开发中的复杂性而诞生的。它...

    Spring中的事务操作、注解及XML配置详解

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> </bean> ``` Spring 中的事务操作、注解及 XML 配置都是为了简化事务管理的过程,使得开发者可以更加...

    Java高频面试题.pdf

    #### Spring Bean 生命周期详解 **Spring框架**中Bean的生命周期管理是面试中的一个重要考察点。主要包括以下几个阶段: 1. **实例化:** - **实例化方式:** - 实例反射:通过反射机制创建Bean实例。 - 工厂...

    详解spring cloud hystrix缓存功能的使用

    总结起来,Spring Cloud Hystrix 的缓存功能通过减少重复请求、保持数据一致性以及减少线程开销,显著提升了服务的响应性能。通过自定义 `HystrixCommand` 类并正确设置缓存 key,我们可以轻松地在项目中启用这一...

    程序员需要知道

    ### 知识点详解 ...**解答**: 在 Tomcat 5 中,如果需要处理 URL 中包含的中文参数,可以通过设置 Tomcat 的连接器 (Connector) 来解决编码问题。例如,可以在 `server.xml` 文件中添加如下配置: ```xml ...

Global site tag (gtag.js) - Google Analytics