`
wolfsquare
  • 浏览: 84230 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

spring配置中bean的循环引用问题及解决方法

阅读更多

问题:Spring+Hibernate的应用中,定义了两个业务Service,这里分别称它们为serivceA,ServiceB。
它们的关系简单点来说是这样的:
serviceA需要引用serviceB,在serviceB中定义了一个接口列表,serverA必须在serviceB初始化时设置进列表。
在纯bean的情况下,也就是这两个类不需要设置其他bean的情况下,循环引用是正常的,可以通过的。例如下面配置所表示:

    <bean id="serviceA" class="A"  autowire="byName"  lazy-init="true">
     <property name="serviceB"><ref local="serviceB"/></property>
    </bean>
 <bean id="serviceB" class="B"  autowire="byName"  lazy-init="true">
     <property name="serviceA"><ref bean="serviceA"/></property>
 </bean>
但是作为一个业务接口,它应该是不需要关心事务,回滚这些无关的东西,
但现实又有这样的需求,所以我们必须保证透明的实现这个功能,于是引
入了AOP方式解决该问题,利用的是Spring自带的org.springframework.t
ransaction.interceptor.TransactionProxyFactoryBean.
重新声明文件如下:
   <bean id="baseTxProxy" lazy-init="true"
      class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="proxyTargetClass"><value>true</value></property>
        <property name="transactionAttributes">
            <props>
  <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
     
    <bean id="serviceA" parent="baseTxProxy">
     <property name="target"><ref local="serviceAImpl"/></property>
    </bean>
   
   <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
     <property name="serviceB">
         <ref bean="serviceB"/>
     </property>
   </bean>
   
    <bean id="serviceB" parent="baseTxProxy" lazy-init="true">
     <property name="target"><ref local="serviceBImpl"/></property>
    </bean>
  
   <bean id="serviceBImpl" class="D" lazy-init="true">
     <property name="serviceA">
         <ref bean="serviceA"/>
     </property>
   </bean>
于是问题就出现了,Spring报了FactoryBeanCircularReferenceException,无法继续完成设置工作。
查看TransactionProxyFactoryBean源码,其实现了FactoryBean和InitializingBean接口,应该是
做了代理之后,两个代理Bean需要等待所有Bean设置完成后才会标识状态为初始化完毕,于是造成了
冲突。

    由于两个业务服务互相调用的路径是不相交的,所以采用了一种变通的方法,在声明serviceA时,
直接定义serviceB:
  <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
     <property name="serviceB">
         <bean class="B"  autowire="byName"/>
     </property>
 </bean>
相当于serviceB和serviceA中使用的serviceB不是同一个实例。
 
 但是如果确实调用重合时怎么办?
 
 解决方法是这样的:
 
 <bean id="serviceAImpl" class="serviceA"  autowire="byName"  lazy-init="true">
     <property name="serviceB">
         <ref bean="serviceBImpl"/>
     </property>
 </bean>
 
  非常简单,serviceAImpl调用时,可能已经在事务环境中了,不需再使用serviceB代理的事务支持,
  于是直接引用serviceB实例。这个方法是我写这篇文章时想到的,-_-!!!,看来知识果真还是好好
  整理呀。

 

分享到:
评论
1 楼 honcur 2013-03-07  
看了一遍,有点感觉,回复后再看一遍,哈哈!

相关推荐

    Spring Bean重复执行两次(实例被构造两次)问题分析

    如果一个BeanA依赖于另一个BeanB,同时BeanB也依赖于BeanA,那么Spring在处理依赖关系时可能会陷入循环引用,导致两个Bean都实例化两次。 3. **@PostConstruct与初始化回调**:Spring允许我们在Bean初始化后执行...

    spring多个动态代理导致循环依赖报错问题解决

    在实际开发中,我们应尽量避免复杂的循环依赖,同时合理配置Spring,以充分利用其特性解决可能出现的问题。了解并熟练掌握以上策略,可以帮助我们更有效地应对Spring中的动态代理导致的循环依赖问题。 为了更好地...

    详解在springmvc中解决FastJson循环引用的问题

    FastJson是阿里巴巴开源的一款高性能的JSON处理工具,广泛应用于Java应用程序中,特别是...通过上述配置方法,开发者可以有效地解决在Spring MVC中使用FastJson时遇到的循环引用问题,确保应用的健壮性和数据的正确性。

    Spring循环依赖案例问题详解.docx

    在Spring框架中,循环依赖(Circular Dependency)是指两个或多个bean之间形成了一种相互引用的关系,使得它们在初始化过程中无法独立完成实例化。在上述案例中,`AuthorService`依赖于`BookService`,而`...

    探秘Spring框架解决循环依赖的高效策略

    Spring框架在处理循环依赖问题上展现出了其卓越的性能和灵活性。循环依赖是软件设计中常见的问题,特别是在大型Java企业应用中,...这个解决方案不仅体现了Spring的灵活性,也为Java开发者提供了宝贵的设计和架构经验。

    Spring循环依赖正确性及Bean注入的顺序关系详解

    在Spring框架中,循环依赖(Circular Dependency)是一个常见的问题,特别是在复杂的系统中。Spring通过其强大的依赖注入(Dependency Injection,DI)机制,有效地解决了这个问题。本文将深入探讨Spring如何处理...

    spring-learn.zip

    但若涉及循环依赖,Spring会提前初始化相关的bean,以解决循环引用。 2. 早周期引用:Spring通过早周期引用来解决部分循环依赖,当检测到一个bean正在被创建,并且其依赖项尚未完全构建时,会暂时保存这个未完成的...

    浅谈Spring解决循环依赖的三种方式

    浅谈Spring解决循环依赖的三种方式 在软件开发中,循环依赖是一个常见的问题,特别是在使用依赖注入框架时。循环依赖是指多个类之间存在循环引用的...开发者可以根据实际情况选择合适的解决方案来解决循环依赖问题。

    Spring循环依赖报错Bean with name ‘**’ has been injected into other beans [**] in its raw version as part

    对于构造器注入的循环依赖,Spring提供了一种称为"循环构造器注入"的解决方案。当Spring检测到这种情况时,它会使用一个特殊的"循环构造器注入代理"来解决。然而,这不是一种推荐的做法,因为它可能导致不可预知的...

    基于SpringBoot构造器注入循环依赖及解决方式

    当Spring试图创建bean并注入其依赖时,如果发现循环依赖,它会抛出`BeanCurrentlyInCreationException`异常,表明存在一个无法解决的循环引用。这通常发生在使用构造器注入时,因为构造器参数必须在bean创建时立即...

    Java-spring框架面试题

    循环依赖其实就是循环引用,也就是两个或两个以上的bean互相持有对方,形成闭环。Spring框架依据三级缓存已经解决了大部分的循环依赖。三级缓存包括: 1. 一级缓存:单例池,缓存已经经历了完整的生命周期,已经...

    java异常解决方案.docx

    + 解决方案:检查 Spring 的 Bean 定义,是否存在语法错误或格式不正确的问题,尝试使用 Spring 的调试工具来检查问题。 * Exception starting filter struts2 The action name cannot be the same as the action ...

    高级开发spring面试题和答案.pdf

    7. **循环依赖解决方案** - Spring通过三级缓存(早期暴露、构造器、属性注入)解决了循环依赖问题。 8. **AOP原理** - Spring的AOP通过动态代理实现,JDK动态代理要求目标对象实现接口,而CGlib动态代理则不需...

    spring.pdf java开发必学

    - **静态工厂注入**:Spring也支持使用静态工厂方法创建Bean,只需要在XML配置中指定工厂类和工厂方法。 理解并熟练掌握Spring的IOC容器及其注入机制,对于Java开发者来说至关重要,因为它可以帮助我们编写更加松...

    基于Spring2.0的Property OverrideConfig Demo

    - 要注意避免循环引用,因为覆盖的属性可能会触发其他bean的初始化,可能导致错误。 通过`PropertyOverrideConfigurerDemo`这个示例,我们可以了解到如何在实际项目中利用Spring 2.0的这一特性,提高应用的可配置...

    java面试Spring.pdf

    Spring通过三级缓存策略来解决循环依赖问题,分别是单例Bean的早绑定、Eager初始化和延迟初始化。 **Spring的自动装配**: Spring支持自动装配,可以通过`autowired`和`@Qualifier`注解来自动匹配和注入Bean。 **...

    Spring3开发实战

    - **配置文件**:XML配置文件是Spring早期的主要配置方式,介绍了如何在XML中定义bean以及它们之间的依赖关系。 #### 三、IoC/DI开发 - **IoC容器原理**:IoC(Inversion of Control)即控制反转,是一种设计模式,...

    Spring基础面试

    - **知识点**: AOP 是一种软件设计模式,用于解决系统中分散的关注点问题。 - **解释**: AOP 通过将业务逻辑之外的通用功能(如日志记录、事务管理等)从业务逻辑中解耦,将其封装为切面(Aspect),然后在运行时...

    springboot常用注解说明

    在处理JSON序列化时,用来解决循环引用的问题,防止无限递归。 12. **@RepositoryRestResource** 当使用`spring-boot-starter-data-rest`时,这个注解可以让Spring Data REST暴露RESTful API接口,方便数据访问。...

    整合Struts + Spring + Hibernate

    - 避免循环引用:在配置Spring时,要注意避免bean间的循环依赖。 - 事务管理:合理配置事务边界,防止事务异常导致的数据不一致。 - 异常处理:在Struts中配置全局异常处理,确保错误信息能正确返回给用户。 ...

Global site tag (gtag.js) - Google Analytics