zoukankan      html  css  js  c++  java
  • (Spring)IOC是如何解决循环依赖的

    前面说到对象的创建,那么在创建的过程中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。

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

  • 相关阅读:
    curl 带 body
    import com.sun.org.apache.xml.internal.security.utils.Base64问题
    动静分离业务解决网页请求不被串改
    java 主动信任证书
    IO 多路复用详解
    spanish-1.1
    spring data JPA entityManager查询 并将查询到的值转为实体对象
    微信二维码支付报错
    军训入营学生发言稿
    电位器控制两个 LED 灯交替闪烁
  • 原文地址:https://www.cnblogs.com/qianjinyan/p/14177837.html
Copyright © 2011-2022 走看看