Spring中的循环依赖及解决,2021Java精选面试实战总结整理
那么在创建B类的Bean的过程中,如果B类中存在一个A类的a属性,那么在创建B的Bean的过程中就需要A类对应的Bean,但是,触发B类Bean的创建的条件是A类Bean在创建过程中的依赖注入,所以这里就出现了循环依赖:
ABean创建–>依赖了B属性–>触发BBean创建—>B依赖了A属性—>需要ABean(但ABean还在创建过程中)
从而导致ABean创建不出来,BBean也创建不出来。
这是循环依赖的场景,但是上文说了,在Spring中,通过某些机制帮开发者解决了部分循环依赖的问题,这个机制就是三级缓存。
三级缓存
singletonObjects中缓存的是已经经历了完整生命周期的bean对象。
singletonFactories中缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的。
解决循环依赖思路分析
A创建时—>需要B---->B去创建—>需要A,从而产生了循环
因为整个过程中,都只有一个A原始对象,所以对于B而言,就算在属性注入时,注入的是A原始对象,也没有关系,因为A原始对象在后续的生命周期中在堆中没有发生变化。
从上面这个分析过程中可以得出,只需要一个缓存就能解决循环依赖了,那么为什么Spring中还需要singletonFactories呢?
因为在一个Bean的生命周期最后,Spring提供了BeanPostProcessor可以去对Bean进行加工,这个加工不仅仅只是能修改Bean的属性值,也可以替换掉当前Bean。
@Componentpublic class User {}@Componentpublic class TestBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 生成了一个新的User对象if (beanName.equals("user")) {System.out.println(bean);User user = new User();return user;}return bean;}}public class Test {public static void main(String[] args) {AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(AppConfig.class);User user = context.getBean("user", User.class);System.out.println(user);}}
com.test.service.User@67gh4rt3com.test.service.User@56tr75b3
所以在BeanPostProcessor中可以完全替换掉某个beanName对应的bean对象。
所以在这种情况下的循环依赖,Spring是解决不了的,因为在属性注入时,Spring也不知道A对象后续会经过哪些BeanPostProcessor以及会对A对象做什么处理。
Spring到底解决了哪种情况下的循环依赖
虽然上面的情况可能发生,但是肯定发生得很少,我们通常在开发过程中,不会这样去做,但是,某个beanName对应的最终对象和原始对象不是一个对象却会经常出现,这就是AOP。
一般过程就是:A类—>生成一个普通对象–>属性注入–>基于切面生成一个代理对象–>把代理对象放入singletonObjects单例池中。
而AOP可以说是Spring中除开IOC的另外一大功能,而循环依赖又是属于IOC范畴的,所以这两大功能想要并存,Spring需要特殊处理。
如何处理的,就是利用了第三级缓存singletonFactories。
上面的Lambda表达式就是一个ObjectFactory,执行该Lambda表达式就会去执行getEarlyBeanReference方法,而该方法如下:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {Object exposedObject = bean;if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);}}}return exposedObject;}
// InstantiationAwareBeanPostProcessorAdapter@Overridepublic Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {return bean;}// AbstractAutoProxyCreator@Overridepublic Object getEarlyBeanReference(Object bean, String beanName) {Object cacheKey = getCacheKey(bean.getClass(), beanName);this.earlyProxyReferences.put(cacheKey, bean);return wrapIfNecessary(bean, beanName, cacheKey);}
那么getEarlyBeanReference方法到底在干什么?
首先得到一个cachekey,cachekey就是beanName。
面试结束复盘查漏补缺
每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。
以下最新总结的阿里P6资深Java必考题范围和答案,包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~
资料免费领取方式:点赞关注后,戳这里免费领取
重要的事说三遍,关注+关注+关注!
更多笔记分享
束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。
以下最新总结的阿里P6资深Java必考题范围和答案,包含最全MySQL、Redis、Java并发编程等等面试题和答案,用于参考~
资料免费领取方式:点赞关注后,戳这里免费领取
重要的事说三遍,关注+关注+关注!
[外链图片转存中…(img-vCS4FQeA-1628590755307)]
[外链图片转存中…(img-i6szJcUg-1628590755309)]
更多笔记分享
Spring中的循环依赖及解决,2021Java精选面试实战总结整理相关推荐
- 一起来踩踩 Spring 中这个循环依赖的坑!
作者:Mythsman blog.mythsman.com/post/5d838c7c2db8a452e9b7082c/ 1. 前言 2. 典型场景 3. 什么是依赖 4. 什么是依赖调解 5. 为什 ...
- 面试:讲一讲Spring中的循环依赖
前言 Spring中的循环依赖一直是Spring中一个很重要的话题,一方面是因为源码中为了解决循环依赖做了很多处理,另外一方面是因为面试的时候,如果问到Spring中比较高阶的问题,那么循环依赖必定逃 ...
- 面试必杀技,讲一讲Spring中的循环依赖
本系列文章: 听说你还没学Spring就被源码编译劝退了?30+张图带你玩转Spring编译 读源码,我们可以从第一行读起 你知道Spring是怎么解析配置类的吗? 配置类为什么要添加@Configu ...
- Spring中的循环依赖
目录 一.什么是循环依赖? 二.Bean的生命周期 2.1 Spring Bean 的生命周期 2.2 Bean 的生成步骤 三.三级缓存 3.1三个缓存分别有什么作用 四.思路分析 4.1 为什么 ...
- Spring中的循环依赖解决详解
目录 1 什么是循环依赖? 1.1 构造器循环依赖 1.2 field属性注入循环依赖 1.3 field属性注入循环依赖(prototype) 2 循环依赖处理 2.1 构造器循环依赖(无法解决) ...
- Spring中的循环依赖问题
Spring的的循环依赖问题 文章目录 Spring的的循环依赖问题 一. 简介 1.什么是循环依赖问题? 2.循环依赖有什么影响? 二. 循环依赖复现 三. 解决方案 1. 重新设计 2 使用 @L ...
- 面试——Spring中的循环依赖
1 什么是Spring循环依赖 // A依赖了B,B是A对象中的一个属性 class A{public B b; }// B依赖了A class B{public A a; } 在普通的代码中,对象之 ...
- map 循环_被问到Spring循环依赖怎么解决?秀给面试官看!内附图解
不知道最近有没有被一道Java面试题刷爆朋友圈,Spring框架的循环依赖如何解决.我收到了不少粉丝的提问,在了解到之后,也去网上查询了一些资料,自己也询问了身边的同事,总结出以下几个方面,今天就和我 ...
- spring相互依赖怎么解决_被问到Spring循环依赖怎么解决?秀给面试官看!内附图解...
不知道最近有没有被一道Java面试题刷爆朋友圈,Spring框架的循环依赖如何解决.我收到了不少粉丝的提问,在了解到之后,也去网上查询了一些资料,自己也询问了身边的同事,总结出以下几个方面,今天就和我 ...
最新文章
- C# 3.0入门系列
- C++ using的三种使用策略以及具体的用法
- mysql在单片机移植_移植MySQL到嵌入式ARM平台
- 创建一个Windows Service应用程序
- Mysql之左连接右连接内连接——示例
- 在没有原始数据的情况下, 我把列线图转换成了网页计算器
- 微信公众号:地图定位
- css 改变图片的背景色,css3实现背景图片颜色修改的多种方式
- SD和SDHC和SDXC卡的区别是什么
- 【原创】ESXI6.7+ikuai爱快搭建软路由(非常详细)
- angularJs监控页面加载完毕
- 3.表数据的CRUD
- Python全栈开发-Mysql知识点总结(中)
- android位置服务与GPS实时定位工具类
- web前端开发基础班课程大纲
- 前端开发 SSR 是什么技术?
- __dict__属性详解
- 51单片机学习笔记(串口通信 LED点阵屏 DS1302)
- 简单几步就可以把pdf转换成excel格式
- 买了SKS的W530
热门文章
- wpf中内容包含在border中_WPF:点击后聚焦边框(WPF: Focus border after click)
- 使用uniapp开发婚庆应用的时候开发公共组件请求网络数据的方式
- reduce_sum() got an unexpected keyword argument 'keep_dims'
- WIDERFACE 数据集
- pytorch 图像归一化
- Pytorch转TensorRT范例代码
- pytorch mseloss bceloss 对比
- epoch,iteration,batch,batch_size
- Pyhon 图片透明化
- python 矩阵常用计算