问题: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实例。这个方法是我写这篇文章时想到的,-_-!!!,看来知识果真还是好好
整理呀。
分享到:
相关推荐
如果一个BeanA依赖于另一个BeanB,同时BeanB也依赖于BeanA,那么Spring在处理依赖关系时可能会陷入循环引用,导致两个Bean都实例化两次。 3. **@PostConstruct与初始化回调**:Spring允许我们在Bean初始化后执行...
在实际开发中,我们应尽量避免复杂的循环依赖,同时合理配置Spring,以充分利用其特性解决可能出现的问题。了解并熟练掌握以上策略,可以帮助我们更有效地应对Spring中的动态代理导致的循环依赖问题。 为了更好地...
在Spring框架中,循环依赖(Circular Dependency)是指两个或多个bean之间形成了一种相互引用的关系,使得它们在初始化过程中无法独立完成实例化。在上述案例中,`AuthorService`依赖于`BookService`,而`...
Spring框架在处理循环依赖问题上展现出了其卓越的性能和灵活性。循环依赖是软件设计中常见的问题,特别是在大型Java企业应用中,...这个解决方案不仅体现了Spring的灵活性,也为Java开发者提供了宝贵的设计和架构经验。
FastJson是阿里巴巴开源的一款高性能的JSON处理工具,广泛应用于Java应用程序中,特别是...通过上述配置方法,开发者可以有效地解决在Spring MVC中使用FastJson时遇到的循环引用问题,确保应用的健壮性和数据的正确性。
在Spring框架中,循环依赖(Circular Dependency)是一个常见的问题,特别是在复杂的系统中。Spring通过其强大的依赖注入(Dependency Injection,DI)机制,有效地解决了这个问题。本文将深入探讨Spring如何处理...
但若涉及循环依赖,Spring会提前初始化相关的bean,以解决循环引用。 2. 早周期引用:Spring通过早周期引用来解决部分循环依赖,当检测到一个bean正在被创建,并且其依赖项尚未完全构建时,会暂时保存这个未完成的...
浅谈Spring解决循环依赖的三种方式 在软件开发中,循环依赖是一个常见的问题,特别是在使用依赖注入框架时。循环依赖是指多个类之间存在循环引用的...开发者可以根据实际情况选择合适的解决方案来解决循环依赖问题。
对于构造器注入的循环依赖,Spring提供了一种称为"循环构造器注入"的解决方案。当Spring检测到这种情况时,它会使用一个特殊的"循环构造器注入代理"来解决。然而,这不是一种推荐的做法,因为它可能导致不可预知的...
当Spring试图创建bean并注入其依赖时,如果发现循环依赖,它会抛出`BeanCurrentlyInCreationException`异常,表明存在一个无法解决的循环引用。这通常发生在使用构造器注入时,因为构造器参数必须在bean创建时立即...
循环依赖其实就是循环引用,也就是两个或两个以上的bean互相持有对方,形成闭环。Spring框架依据三级缓存已经解决了大部分的循环依赖。三级缓存包括: 1. 一级缓存:单例池,缓存已经经历了完整的生命周期,已经...
+ 解决方案:检查 Spring 的 Bean 定义,是否存在语法错误或格式不正确的问题,尝试使用 Spring 的调试工具来检查问题。 * Exception starting filter struts2 The action name cannot be the same as the action ...
7. **循环依赖解决方案** - Spring通过三级缓存(早期暴露、构造器、属性注入)解决了循环依赖问题。 8. **AOP原理** - Spring的AOP通过动态代理实现,JDK动态代理要求目标对象实现接口,而CGlib动态代理则不需...
- **静态工厂注入**:Spring也支持使用静态工厂方法创建Bean,只需要在XML配置中指定工厂类和工厂方法。 理解并熟练掌握Spring的IOC容器及其注入机制,对于Java开发者来说至关重要,因为它可以帮助我们编写更加松...
- 要注意避免循环引用,因为覆盖的属性可能会触发其他bean的初始化,可能导致错误。 通过`PropertyOverrideConfigurerDemo`这个示例,我们可以了解到如何在实际项目中利用Spring 2.0的这一特性,提高应用的可配置...
Spring通过三级缓存策略来解决循环依赖问题,分别是单例Bean的早绑定、Eager初始化和延迟初始化。 **Spring的自动装配**: Spring支持自动装配,可以通过`autowired`和`@Qualifier`注解来自动匹配和注入Bean。 **...
- **配置文件**:XML配置文件是Spring早期的主要配置方式,介绍了如何在XML中定义bean以及它们之间的依赖关系。 #### 三、IoC/DI开发 - **IoC容器原理**:IoC(Inversion of Control)即控制反转,是一种设计模式,...
- **知识点**: AOP 是一种软件设计模式,用于解决系统中分散的关注点问题。 - **解释**: AOP 通过将业务逻辑之外的通用功能(如日志记录、事务管理等)从业务逻辑中解耦,将其封装为切面(Aspect),然后在运行时...
在处理JSON序列化时,用来解决循环引用的问题,防止无限递归。 12. **@RepositoryRestResource** 当使用`spring-boot-starter-data-rest`时,这个注解可以让Spring Data REST暴露RESTful API接口,方便数据访问。...
- 避免循环引用:在配置Spring时,要注意避免bean间的循环依赖。 - 事务管理:合理配置事务边界,防止事务异常导致的数据不一致。 - 异常处理:在Struts中配置全局异常处理,确保错误信息能正确返回给用户。 ...