Spring Bean循环依赖

        多个Bean之间互相依赖并形成一个闭环叫做循环依赖。Bean的依赖注入分为构造器注入和Setter注入两种方式。
        在采用构造器注入的方式配置Bean时,很可能会产生循环依赖的情况,Spring启动时会抛出BeanCurrentlyInCreationException异常。如果采用构造器注入方式,解决循环依赖的手段是打破循环,可以让Spring懒加载其中一个Bean(使用@Lazy注解),不完全初始化Bean,创建一个代理然后将它注入另一个Bean,注入的Bean在第一次需要时才完全创建它,demo如下:
@Component
public class CircularDependencyA {

    private CircularDependencyB circB;

    @Autowired
    public CircularDependencyA(@Lazy CircularDependencyB circB) {
        this.circB = circB;
    }
}
        还可以完全放弃构造器注入,只 使用setter方法注入的方式。 除了极少数例外,大部分的循环依赖都是可以避免的。 Spring的Autowired注解也是通过setter方式注入的。使用setter方式注入是在Bean构造(初始化)之后进行的,Spring会使用三级缓存来解决循环依赖。

三级缓存解决循环依赖

案例介绍:
        lagouBean有一个属性引用itBean,itBean也有一个属性引用lagouBean,然后有一个日志的横切逻辑增强lagouBean。lagouBean与itBean形成循环依赖。
容器在启动时处理流程如下:
1.实例化lagouBean,创建lagouBeanFactory放入三级缓存;
2.lagouBean依赖属性itBean,所以需要实例化itBean,创建itBeanFactory放入三级缓存;
3.由于itBean依赖lagouBean,所以用三级缓存中的lagouBeanFactory创建一个lagouBean的代理对象放入二级缓存并引用,并移除三级缓存中的lagouBeanFactory;
4.此时itBean创建完成,将itBean放入一级缓存,并移除三级缓存中的itBeanFactory;
5.itBean实例化完成后会继续实例化lagouBean,从二级缓存中找到lagouBean继续装配;
6.lagouBean装配上一级缓存中的itBean,完成实例化放入一级缓存中,两个Bean都创建完毕;
实例化过程如图:
一级缓存是单例池,存放完整的SpringBean。二级缓存存放早期单例对象。三级缓存存放单例工厂对象。三级缓存的主要作用就是产生代理对象。此案例之所以需要一个日志的横切逻辑是为了说明三级缓存的作用。如果没有横切增强时,使用二级缓存就能处理循环依赖。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值