Spring解决循环依赖
1.Spring解决循环依赖
什么是循环依赖:比如A引用B,B引用C,C引用A,它们最终形成一个依赖环。
循环依赖有两种
1、构造器循环依赖
构造器注入导致的循环依赖,Spring是无法解决的,只能抛出BeanCurrentlyInCreationException异常。因为构造器注入时的参数需要依赖bean的实例。所以无法解决循环依赖的问题。
如在创建A的实例时,发现依赖B,那将去创建B的实例,又发现依赖C,则又去创建C,最终在创建C的时候发现依赖A,从而形成一个环,没办法创建。
Spring容器每一个正在创建的bean标识符放在一个“当前创建bean池”中,这个池是一个set集合
private final Set<String> singletonsCurrentlyInCreation = Collections.synchronizedSet(new HashSet());
bean标识符将一直保持在这个池中,因此如果bean创建过程中发现自己已经在当前创建bean池中时,将抛出BeanCurrentlyInCreationException异常表示循环依赖。而对于创建完毕的bean将从“当前创建bean”池中清除掉。
2、setter循环依赖
表示通过setter注入方式构成的循环依赖。对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器创建实例但未完成其他步骤如setter注入的bean来完成的。提前暴露一个
单例工厂方法,从而使其他bean能引用该bean。
而且只能解决单例作用域的bean循环依赖。
步骤:
1、Spring容器创建单例A bean,首先通过无参构造器创建bean,并暴露一个ObjectFactory返回一个在创建中的bean,并将A标识符放在当前创建bean池中。然后通过setter方式注入
依赖B
2、Spring容器创建单例B bean,首先通过无参构造器创建bean,并暴露一个ObjectFactory返回一个在创建中的bean,并将B标识符放在当前创建bean池中。然后通过setter方式注入
依赖C
3、Spring容器创建单例C bean,首先通过无参构造器创建bean,并暴露一个ObjectFactory返回一个正在创建中的bean,并将C标识符放在当前创建bean池中。然后setter方式
注入A,进行注入A时由于提前暴露了ObjectFactory工厂,所以使用它返回提前暴露一个创建中的bean。
4.然后再依次完成setter注入C完成B创建,依赖注入B完成A创建。
prototype范围的依赖处理:spring也无法完成依赖注入,因为Spring容器不进行缓存prototype作用域的bean,因此无法暴露一个创建中的bean。(单例范围下是通过放入缓存中的ObjectFactory来创建实例)
缓存objectFactory是将ObjectFactory放入map中
private final Map<String, ObjectFactory> singletonFactories = new HashMap();
this.singletonFactories.put(beanName, singletonFactory);
this.addSingletonFactory(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
// 在此完成aop动态织入
return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
}
});
aop将advice动态织入bean中也是在将创建bean的工厂放在单例工厂集合中时织入的。
常规bean的创建是在AbstratAutowireCapableBeanFactory的doCreateBean方法中创建的。
创建完成的bean,如果配置了destory-method则放在LinkHashMap中,便于在销毁时调用。
private final Map<String, Object> disposableBeans = new LinkedHashMap();
Spring解决循环依赖的更多相关文章
- 浅谈Spring解决循环依赖的三种方式
引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种: ...
- Spring解决循环依赖,你真的懂了吗?
导读 前几天发表的文章SpringBoot多数据源动态切换和SpringBoot整合多数据源的巨坑中,提到了一个坑就是动态数据源添加@Primary接口就会造成循环依赖异常,如下图: 这个就是典型的构 ...
- 曹工说Spring Boot源码(29)-- Spring 解决循环依赖为什么使用三级缓存,而不是二级缓存
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 建议收藏!利用Spring解决循环依赖,深入源码给你讲明白!
前置知识 只有单例模式下的bean会通过三级缓存提前暴露来解决循环依赖的问题.而非单例的bean每次获取都会重新创建,并不会放入三级缓存,所以多实例的bean循环依赖问题不能解决. 首先需要明白处于各 ...
- Spring如何解决循环依赖问题
目录 1. 什么是循环依赖? 2. 怎么检测是否存在循环依赖 3. Spring怎么解决循环依赖 本文主要是分析Spring bean的循环依赖,以及Spring的解决方式. 通过这种解决方式,我们可 ...
- 一张图彻底理解Spring如何解决循环依赖!!
写在前面 最近,在看Spring源码,看到Spring解决循环依赖问题的源码时,不得不说,源码写的太烂了.像Spring这种顶级的项目源码,竟然存在着这种xxx的代码.看了几次都有点头大,相信很多小伙 ...
- 彻底理解Spring如何解决循环依赖
Spring bean生命周期 可以简化为以下5步. 1.构建BeanDefinition 2.实例化 Instantiation 3.属性赋值 Populate 4.初始化 Initializati ...
- 【Spring】 Spring如何解决循环依赖的问题?
https://mp.weixin.qq.com/s/FtbzTMxHgzL0G1R2pSlh-A 通常来说,如果问Spring内部如何解决循环依赖,一定是单默认的单例Bean中,属性互相引用的场景. ...
- 听说你还不知道Spring是如何解决循环依赖问题的?
Spring如何解决的循环依赖,是近两年流行起来的一道Java面试题. 其实笔者本人对这类框架源码题还是持一定的怀疑态度的. 如果笔者作为面试官,可能会问一些诸如"如果注入的属性为null, ...
随机推荐
- 重磅干货免费下载!阿里云RDS团队论文被数据库顶会SIGMOD 2018收录
ACM SIGMOD数据管理国际会议是由美国计算机协会(ACM) 数据管理专业委员会(SIGMOD)发起.在数据库领域具有最高学术地位的国际性学术会议. SIGMOD和另外两大数据库会议VLDB.IC ...
- php htmlspecialchars()函数 语法
php htmlspecialchars()函数 语法 作用:函数把预定义的字符转换为 HTML 实体.预定义的字符有:& (和号)成为 &," (双引号)成为 " ...
- 状压 DP:[USACO06NOV] Corn Fields,[USACO13NOV] No Change
[USACO06NOV] Corn Fields (试题来源:Link ) 题目描述 Farmer John has purchased a lush new rectangular pasture ...
- CSS定位,转载的
转自:http://www.cnblogs.com/jiqing9006/archive/2012/07/26/2610586.html 层级关系为:<div ——————————— posit ...
- Caused by: java.lang.ClassNotFoundException: com.mchange.v2.cfg.MConfig
出错原因:c3p0 为0.9.5.2版本 而使用了 mchange-commons-java 的版本为0.2.3.4,mchange-commons-java 的版本太高了, 将mchange-com ...
- AGC037C Numbers on a Circle
题目大意 给你一个序列a和序列b 每次操作是a[i]+=a[i-1]+a[i+1] 问a经过最少几次操作可以得到b 分析 用堆维护a 每次取出最大的 撤销操作直到不能撤销 将新数放入堆 不断维护即可 ...
- linux 修改系统字符集,查看字符
修改系统字符集 # cd /etc/sysconfig # vi i18n -------------------文件内容------------------ LANG="zh_CN.GB1 ...
- Java学习之Thread方法
一.sleep()方法:在同步中,释放CPU执行权,不释放同步锁,意味着程序停止 二.停止线程方法:原理:run执行完成 1.设置标记 class StopThread implements Runn ...
- win10下cmd备注
要复制cmd里的字符串,右键选标记,选中待复制的字符串,ctrl+c 复制,ctrl+v粘贴内容(或者右键选择复制).这项操作支持复制cmd里的内容到其他地方,如txt里 win10之前cmd不支持c ...
- Python笔记(五)_内置函数BIF
查看所有的内置函数:dir(__builtins__) abs() 获取绝对值 max() 返回给定元素中的最大值 min() 返回给定元素中的最小值 sum() 求和 reverse ...