spring循环引用

本文深入探讨了Spring框架中bean的循环引用问题,分析了四种不同场景下(setter注入单例、setter注入原型、构造注入单例、构造注入原型)的报错情况及其原因。在setter注入单例的情况下,由于对象被缓存,因此能够成功避免循环引用;而在构造注入场景中,由于对象在构造过程中尚未被缓存,导致报错。文章揭示了Spring处理循环依赖的机制,为理解和解决这类问题提供了宝贵指导。
摘要由CSDN通过智能技术生成

当spring的bean存在循环引用时,有的情况下会报错,而有的情况下不会。影响是否会报错的因素是:1.属性是通过构造方法传递值还是通过setter传递值。2.属性是否是单例的。下面解释了四种情况、是否会报错、报错或不报错的原因。

前置知识

不论是singleton还是prototype,在创建的过程中都会有一个xxxCurrentlyInCreation的Set对象,这个Set中存放的key表示正在创建的对象,但是还没有创建完成。在对象new之前先检查这个Set中没有要创建的key,然后把要创建的对象的key放入Set,等对象完全创建完成后再把key从Set中移除;在对象创建前检查这个Set中存在要创建的key时,则抛出org.springframework.beans.factory.BeanCurrentlyInCreationException这个类型的异常。

对于singleton的对象,在创建的过程中,在创建完对象以后,setter方法执行前,会放到org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.singletonFactories属性中,以供后面依赖的对象创建时使用。

这里区别一下上面的过程的先后顺序。当getBean的时候,如果是单例,则先从之前缓存的对象中取,如果有则直接返回。否则去new,new的时候再用xxxCurrentlyInCreation的Set去去重,如果在xxxCurrentlyInCreation的Set中则抛异常。

在后面的解释中,我们假设一个a -> b -> a 的循环依赖。

setter - singleton

不报错。

原因:singleton的对象创建的过程中,会被存放进org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.singletonFactories属性中,在后面的依赖循环中需要这个单例的对象时,在这个map中取出即可。
那这个对象时在何时被put的呢? 在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean -> org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.addSingletonFactory中,在上述的doCreateBean中调用addSingletonFactory方法的地方还有一句注释: Eagerly cache singletons to be able to resolve circular references even when triggered by lifecycle interfaces like BeanFactoryAware.
a对象创建完,被put到org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.singletonFactories,然后在执行a的setter中依赖b,构造b的过程中依赖a,这时a已经在map中了,可以直接获取,而不需要再new。

setter - prototype

报错。错误如下。

org.springframework.beans.factory.BeanCurrentlyInCreationException Requested bean is currently in creation: Is there an unresolvable circular reference?

原因:getBean的时候,先构造a对象,然后通过setter方法设置属性,设置的时候构造依赖的对象b。new b完成,然后执行setter,需要构造a,这时a已经在xxxInCreation的Set中,所以抛异常。

construct - singleton

报错。错误如下。

org.springframework.beans.factory.BeanCurrentlyInCreationException Requested bean is currently in creation: Is there an unresolvable circular reference?

原因:getBean的时候,检查构造方法,创建构造方法里需要的对象,所以成环。相比于 setter - singleton 这种情况,它抛了异常,而setter - singleton没有抛出异常,区别在哪里呢?因为把单例对象放入org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.singletonFactories的时机是在对象创建后,setter方法执行前。这种情况下在执行构造方法的过程中的依赖,所以之前第一个a还没有构造完成,还没有被放进org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.singletonFactories

construct - prototype

报错。错误如下。

org.springframework.beans.factory.BeanCurrentlyInCreationException Requested bean is currently in creation: Is there an unresolvable circular reference?

原因:getBean的时候,检查构造方法,创建构造方法里需要的对象。所以成环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值