spring循环依赖为什么不是二级缓存,spring一级缓存能解决循环依赖吗

  spring循环依赖为什么不是二级缓存,spring一级缓存能解决循环依赖吗

  00-1010前言1什么是循环依赖2如何解决无法解决的循环依赖3?

  00-1010所谓的三级缓存,不过是三个可以视为全局变量的映射。Spring的源代码使用了这种代码风格,先将数据放入容器,等待使用,然后销毁它。

  Spring的初始化过程大致有四步:

  创建beansFactory,加载配置文件,解析配置文件,转换beanDefination,获取bean的所有属性和依赖,以及用于初始化的各种处理器等。刷新beanFactory容器,初始化所有单例bean,注册所有单例bean并返回可用容器。我们说的循环依赖是注入bean属性的第四步出现的问题。

  

目录

循环依赖就是:

 

  假设有A和B两个类,B需要注入A,A需要注入B,因为A注入B的时候B还没有创建,B创建的时候A也不能创建,所以存在死循环问题。

  

前言

我们都知道AOP是Spring的一个重要核心思想,它的实现是基于动态代理的。也就是说,我们的Bean实际上有很高的概率生成代理类。我们先来看看没有代理的情况:

 

  Bean的初始化大概是这样的:

  根据以上步骤可以看出,bean初始化是一个相当复杂的过程。如果在初始化bean A时发现bean A依赖于bean B,也就是说在初始化的第四步填充属性时需要注入bean B。此时,在B还没有初始化之前,需要暂停A,先初始化B,所以将新生成的A对象直接放在容器映射中显然是不合适的。半成品怎么用?所以需要提供一个可以标记正在创建的bean(A)的映射,可以提前暴露出来,让其他bean依赖。如果在初始化A所依赖的bean B时发现B也需要注入一个依赖(即循环依赖发生),那么B可以直接从正在创建的beanMap中获取A对象(正在创建),注入到A中,然后完成B的初始化,返回给正在注入属性的A,最后是A。

  如果没有循环依赖,A依赖B,也就是B依赖C创建C,创建后一步一步走回去就够了,不需要任何缓存。所以为了解决循环依赖而设置的一级缓存(二级、三级缓存)之后的其他缓存,其实就是我们成熟的Bean,可以直接使用。

  我们去看一下源码:

  从源代码中我们可以看到,三级缓存不是实例化的Bean,而是一个工厂。为什么?循环依赖在实际应用中可能存在,但很少。简单的应用场景有:控制器注入服务,服务注入映射器。只有复杂的服务。服务可能相互引用,可能出现循环依赖。因此,为了出现循环依赖才去解决,不出现就不解决,虽然支持循环依赖,但是,只有在出现循环依赖时才真正暴露早期对象,则不然,只暴露了一个获取bean的方法,而bean并没有真正暴露,因为这个方法不会被执行。这个模块的实现是singletonFactories,只缓存了一个单例bean工厂.为什么是一个工厂?还是这个工厂的作用?三级缓存bean工厂的getObject方法实际上实现了getEarlyBeanReference。如果需要对对象进行代理(BeanPostProcessors-SmartInstantiawareBeanPostProcessor存在),则提前生成代理对象。

  三级缓存解决了所有问题。二级缓存是做什么用的?为什么三级缓存不直接叫二级缓存?这应该在使用缓存时决定:

  此时这个方法中的判断逻辑是:

  一级缓存中没有对象A,实际上是在二级缓存中创建的,对象并不是最终从三级缓存中获取的。从三级缓存中获取对象后,将其从三级缓存中删除,然后放入二级缓存。因为它最初是放在工厂的三级缓存中,所以调用getEarlyBeanReference方法从三级缓存中获取对象。这个方法的作用是,如果对象需要代理,返回代理类,如果不需要代理,返回native type,注入属性。

  给大家一个循环依赖的流程图,大家一看便知:

  /strong>

  

 

  看到了吗,如果AB都需要代理,我们在A的属性注入时创建了B,但是此时A还是原生的A,但是我们需要代理A,而代理A在B注入A时已经创建并放入二级缓存中了,我们直接从二级缓存拿然后替换原生A即可。

  所以,我理解的是二级缓存是为了应对代理这个情况而生的至此,循环依赖的问题已经完美解决

  

 

  

3无法解决的循环依赖

构造函数循环依赖:

 

  如果我们的成员属性是在构造函数里呢?首先要解决循环依赖就是要先实例化然后放入三级缓存暴露出来,那么如果是构造函数这一步循环依赖,实例化的时候就会产生无限递归创建,所以不能解决

  多例的循环依赖:

  如果是多例的,在容器初始化的时候,不会去创建,所以早期没有放入到三级缓存中暴露出来,所以无法解决循环依赖,会报错

  到此这篇关于Spring解决循环依赖问题及三级缓存的作用的文章就介绍到这了,更多相关Spring解决循环依赖问题内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • spring编程式事务处理,spring编程事务
  • spring编程式事务处理,spring编程事务,详解Spring学习之编程式事务管理
  • spring的核心功能模块有几个,列举一些重要的spring模块
  • spring的核心功能模块有几个,列举一些重要的spring模块,七个Spring核心模块详解
  • spring注解和springmvc的注解,SpringMVC常用注解
  • spring注解和springmvc的注解,SpringMVC常用注解,详解springmvc常用5种注解
  • spring实现ioc的四种方法,spring的ioc的三种实现方式
  • spring实现ioc的四种方法,spring的ioc的三种实现方式,简单实现Spring的IOC原理详解
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况,Spring事务失效问题分析及解决方案
  • spring5.0新特性,spring4新特性
  • spring5.0新特性,spring4新特性,spring5新特性全面介绍
  • spring ioc以及aop原理,springmvc aop原理
  • spring ioc以及aop原理,springmvc aop原理,深入浅析Spring 的aop实现原理
  • Spring cloud网关,spring cloud zuul作用
  • 留言与评论(共有 条评论)
       
    验证码: