• Spring ioc(4)---如何解决循环依赖


    前面说到对象的创建,那么在创建的过程中Spring是怎么又是如何解决循环依赖的呢。前面提到有个三级缓存。就是利用这个来解决循环依赖。打个比方说实例化A的时候,先将A创建(早期对象)放入一个池子中。这个时候虽然属性没有赋值,但是容器已经能认识这个是A对象,只是属性全是null而已。在populateBean方法中对属性赋值的时候,发现A依赖了B,那么就先去创建B了,又走一遍bean的创建过程(创建B)。同样也会把B的早期对象放入缓存中。当B又走到populateBean方法的时候,发现依赖了A,好吧,我们又去创建A呗,但是这个时候去创建A,发现我们在缓存能找到A(早期对象)了。就可以把B的A属性赋值了,这个时候B就初始化完成了。现在回到A调用的populateBean方法中。返回的就是B对象了,对A的B属性进行赋值就可以了。流程如下:

    这就是Spring IOC如何解决循环依赖的原理,但是IOC无法解决两种循环依赖,一种是非单例对象的,因为非单例对象不会放入缓存的。每次都是需要创建。二是通过构造器注入,也无法解决。从上面的流程可以看出,调用构造器创建实例是在createBeanInstance方法,而解决循环依赖是在populateBean这个方法中,执行顺序也决定了无法解决该种循环依赖。对于这种,如果喜欢使用lombok的@RequiredArgsConstructor注解的小伙伴就需要注意了,这个注解会生成一个带所有属性的构造方法。通过idea直接点开对应的class文件就可以看不看这个构造方法了。

    问题:解决循环依赖一定要三级缓存嘛?

    关键代码位置:org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#addSingletonFactory

    首先我们的一级缓存是单例缓存池singletonObjects),二级缓存是早期对象(earlySingletonObjects),三级缓存是一个包裹对象ObjectFactory(registeredSingletons),通过getObject获取到早期对象。

    从上面的流程来看,实际上二级缓存已经可以解决循环依赖了,那么为什么Spring还要包裹出来一个三级缓存呢?

    Spring Ioc(3)---bean的实例化中的源码分析我们可以看到调用三级缓存中的getObject方法实际上是调用的org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference这个方法。

    那么我就看看这个方法里面干了些什么事情:

    执行SmartInstantiationAwareBeanPostProcessor这个类型处理器的getEarlyBeanReference方法。

    断点调试,发现Spring原生中实现了这个接口的类org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter,实际上什么事情都没有干,直接返回了,

    但是如果是AOP要切的对象,会在这里生成代理对象返回,AOP流程:Spring aop(1)--- 寻找切面和代理对象执行流程源码分析

     org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference。

    所以说第三级缓存其实是为了解决代理对象之间的循环依赖。

  • 相关阅读:
    response.redirect on asp.net is a 302 jump action
    什么吃掉了我的硬盘?
    百度流量统计将会影响搜索的排名
    发邮件 python
    bottle template usage
    想提神,喝中药,咖啡可可没用的
    企业退信的常见问题?
    用UnixBench测试VPS性能 判别是否值得购买
    域名注册及免费空间and企业邮箱
    LNMP一键安装包是什么?
  • 原文地址:https://www.cnblogs.com/nijunyang/p/12365048.html
Copyright © 2020-2023  润新知