首页 > 其他分享 >Spring的循环依赖

Spring的循环依赖

时间:2022-10-25 11:15:04浏览次数:91  
标签:初始化 缓存 Spring 代理 依赖 循环

Spring循环依赖

1 循环依赖解决及概述

(1)循环依赖的问题描述和Spring解决流程

@Component
public class A{
	@Autowired
    private B b;
}

@Component
public class B{
    @Autowired
    private A a;
}

循环依赖, 形式如上.

spring按照顺序初始化Bean:

第一步创建A, 构建A的BeanFactory放置在三级缓存中,然后实例化A, 注入属性, 发现A需要B, 在一级二级三级缓存中没有发现B, 开始创建B;

第二步, 创建B, 构建B的BeanFactory放置在三级缓存中, 然后实例化, 注入属性, 发现B需要A, 于是从一级二级缓存寻找A, 无果, 在三级缓存中找到A的BeanFactory, 从中取出 A(或A的代理对象), 然后将A放置在二级缓存中, 将其从三级缓存中删除, B初始化完成, 进入到一级缓存;

第三步, A从一级缓存中获取到初始化完成的B, A也初始化完成, 进入到一级缓存, A 和 B都初始化完成.

需要注意的是:

三级缓存的目的主要是延迟生成代理对象.

正常情况下, Bean的代理对象是在初始化完成后才生成的, 然而, 如果产生了循环依赖, spring出于开发者考虑, 如果对于Bean进行了AOP代理, 那么对于这个Bean的依赖, 开发者也必然是想注入其代理对象的.

因此, 在产生循环依赖的情况下, Bean的代理对象会提前生成, 将该代理对象传递给依赖者.

亦即是说, Bean的代理对象生成可能会有两个时间点.

在第二步中, spring会进行判断, 如果目标对象被代理, 则提前生成代理对象, 否则在对象初始化完成后再生成代理对象.

产生循环依赖的情况下, 被依赖对象的初始化完成需要从三级缓存中**取出BeanFactory中的实例引用, 此时会作一个判断, **判断该实例是否被增强(AOP), 来决定是否返回代理对象(提前生成代理对象).

在不产生循环依赖的情况下,不需要从beanFactory取出, 因此不需要进行该判断, 正常情况下, 在bean初始化完成后,进行代理对象的生成.

二级缓存的目的则是解决多个Bean相互依赖的问题

@Component
public class A{
	@Autowired
	private B b;
	
	@Autowired
	private C c;
}

@Component
public class B{
    @Autowired
    private A a;
}

@Component
public class C{
    @Autowired
    private C c;
}

如上所示, 当B进行初始化后, A被放置在二级缓存中, 等C进行初始化的时候, 从二级缓存中取出.

参考:

Spring是怎么解决循环依赖的? - 简书 (jianshu.com)

Spring三级缓存 - 简书 (jianshu.com)

面试必杀技,讲一讲Spring中的循环依赖 - 程序员DMZ - 博客园 (cnblogs.com)

spring + spring mvc + tomcat 面试题(史上最全) - 疯狂创客圈 - 博客园 (cnblogs.com)

2 关于循环依赖的种类

spirng中注入的方式分为:

  • 基于构造器的注入
  • 基于setter的注入

另外又涉及到Bean的作用域:

  • 单例-singleton
  • 原型-prototype
  • request
  • session
  • globle-session

因此循环依赖可以分为三类:

  • 单例状态下基于setter注入方式的循环依赖
  • 单例状态下基于构造器的注入方式的循环依赖
  • 多例状态下的循环依赖

对于多例状态下的循环依赖,无法解决

基于构造器注入方式的单例循环依赖,可以采用@lazy的方式,延迟加载以解决

spring本身的机制,只能解决基于setter方式注入的单例循环依赖

资料来源

Spring面试题必知必会-循环依赖概览:

https://blog.csdn.net/a745233700/article/details/80959716

Spring循环依赖详解:

https://blog.csdn.net/a745233700/article/details/110914620

标签:初始化,缓存,Spring,代理,依赖,循环
From: https://www.cnblogs.com/wang-jifeng/p/16824184.html

相关文章

  • SpringCloud-04 Feign学习笔记
    @​​TOC​​一、什么是Feign?Feign是声明式WebService客户端,它让微服务之间的调用变得更简单,类似controller调用service。SpringCloud集成了Ribbon和Eureka,可以使用Feigin......
  • SpringCloud-05 Hystrix学习笔记
    @[Toc]一、Hystrix简介1、Hystrix是什么?流量高峰时,一个单节点的宕机或延迟,会迅速导致所有服务负载达到饱和。应用中任何一个可能通过网络访问其他服务的节点,都有可能成为......
  • SpringBoot(五)SpringBoot拦截器
    1.继承HandlerInterceptorAdapter,实现preHandle前置处理器,returntrue则进行后续处理,实现postHandle,afterCompletion后置处理。2.实现WebMvcConfigurer,SpringBoot2......
  • 记一次springboot项目自定义HandlerMethodArgumentResolver不生效原因与解法
    前言本文素材的来源自业务部门技术负责人一次代码走查引发的故事,技术负责人在某次走查成员的代码时,发现他们的业务控制层大量充斥着如下的代码@PostMapping("add")p......
  • Spring AOP 报错:Error creating bean with name 'student' defined in file
    问题概述SpringAOP报错,一直显示:Errorcreatingbeanwithname'student'definedinfile的报错。从五个方向排查:第一,aspectj包的scope是不是runtime;第二,jar包是......
  • 7-2 双向循环链表应用
    已知p指向双向循环链表中的一个结点,其结点结构为data、prior、next三个域,实现交换p所指向的结点和它的前缀结点的顺序。#include<iostream>#defineElemTypeintusing......
  • SpringMvc学习——整合SSM
    1、创建项目结构   2、导入坐标<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2......
  • 在非controller层中依赖注入为null问题
    我们在项目中,一般在controller层中注入service接口,在service层中注入其它的service接口或者mapper接口都是可以的,但是如果我们要在我们自己封装的Utils工具类中或者非contr......
  • springmvc中web.xml模板
    myweborg.springframework.web.servlet.DispatcherServlet<init-param><param-name>contextConfigLocation</param-name><param-value>classpat......
  • Springboot数据库的配置问题
    mysql时区问题先前的代码如下spring:datasource:url:jdbc:mysql://localhost:3306/testusername:rootpassword:110120driver-class-name:com......