spring 循环依赖引出的问题

首先看一下异常:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'elementServiceFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:297)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:216)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:671)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:610)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1076)
	... 97 more

 

看了对象的关联关系,的确存在这个问题,最终问题解决也很简单:

网上有一种说法是在bean上加lazy-init="true"

    <bean name="elementServiceFactory" class="gov.sdta.dtss.service.info.ElementServiceFactory" lazy-init="true">

 参照:http://blog.youkuaiyun.com/cooper_lyt/archive/2008/11/25/3367684.aspx

但是我试了,这个方式对我不起作用。

 

于是我找到了另外的方式,使用set方式注入(原来是构造注入的):

参照:http://hi.baidu.com/dongbeiman/blog/item/95b39111649a5777ca80c4b1.html

然后问题就ok了。

 

下面说下我的问题的现象:

 

相同的代码不同的机器运行,同样的环境,一个报上述错误,一个正常启动。没办法,只好debug了,搞好spring 2.5.6的代码,首先找到了报错的大体位置“DefaultSingletonBeanRegistry”,相关代码如下:

 

private final Set singletonsCurrentlyInCreation = Collections.synchronizedSet(new HashSet());

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
		Assert.notNull(beanName, "'beanName' must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				beforeSingletonCreation(beanName);
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet();
				}
				try {
					singletonObject = singletonFactory.getObject();
				}
				catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Iterator it = this.suppressedExceptions.iterator(); it.hasNext();) {
							ex.addRelatedCause((Exception) it.next());
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				addSingleton(beanName, singletonObject);
			}
			return (singletonObject != NULL_OBJECT ? singletonObject : null);
		}
	}


protected void beforeSingletonCreation(String beanName) {
		if (!this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}
 

singletonsCurrentlyInCreation 是一个set,当出现循环依赖的时候就会出现相同name的bean被同时add两次,而失败,抛出BeanCurrentlyInCreationException的异常。这个是很正常的。但是为设么另外一台机器没这个问题呢?

 

debug加上condition断下来发现,相同的beanName,是由不同的类引用的,这个是正常的,但是我的第一次断下来是有循环依赖的引用的,而他的则是另外一个类,这个类与出问题的类并没有循环依赖的问题,于是他的没有报错,而我的则报错了。

 

这说明一个问题,spring初始化的时候bean的初始化顺序是没先后顺序的,这个以前也听说过,那么怎么能调整先后顺序呢?找了一些资料(http://guoliangqi.iteye.com/blog/632697),加了initmethod,没有效果,于是放弃了,但是我想知道我的顺序是什么样子,于是再下断点,在DefaultListableBeanFactory中找到了如下代码:

 

public void preInstantiateSingletons() throws BeansException {
		if (this.logger.isInfoEnabled()) {
			this.logger.info("Pre-instantiating singletons in " + this);
		}

		synchronized (this.beanDefinitionMap) {
			for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
				String beanName = (String) it.next();
				RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
				if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
					if (isFactoryBean(beanName)) {
						FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
						if (factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit()) {
							getBean(beanName);
						}
					}
					else {
						getBean(beanName);
					}
				}
			}
		}
	}
 

 

在:resolvableDependencies.keySet()中,我拿到了list中的所有内容,大概有800多个,而且前4个还是spring的bean(org.springframework.context.annotation.internalPersistenceAnnotationProcessor)

 

比对了我的list与正常启动机器的list,的确两个bean的顺序一个在前一个在后,那这个时候问题的现象就好解释了。

相同的代码,不同机器的map的hash是不一样的,因此导致keyset之后,拿到的list排序也不一样,所以他的能起来。

 

因为他的类引用了有循环依赖问题的类,并将之正确常见出来,而我则在床两两个循环依赖的类的时候互相创建,导致创建失败。(注:不知道真实远离,我是这么理解的,知道原理的情指正,谢谢。)

 

所以,这个看起来非常诡异的问题,就这样搞定了。折腾了一天才搞定,不过还好,有不少进步。

 

最后提醒大家,碰到问题,不要说人品问题,一定要找出“人品问题”到底是哪里的问题,以便把这个人品值加上去 :)

 

这篇文章可以参考: http://www.goldendoc.org/2010/11/spring-ioc%E4%B9%8Bbeanfactory/

 

异步处理优化:多线程线程池与消息队列的选择与应用 本文讨论了两种常见的异步处理方式:多线程线程池和消息队列(MQ)。通过将非核心逻辑异步化,可以提升系统的性能和响应速度。多线程线程池适用于本地并发任务,适合需要快速响应的场景,但无法处理跨服务任务。消息队列则适用于分布式系统,能够解耦服务并保证任务的可靠性和顺序性,适合处理高并发和高可靠性要求的任务。文章提供了实际代码示例,帮助开发者根据业务需求选择合适的异步处理方式。 阅读详情

相关推荐

修复后找不到ip 黑群晖_黑群晖引导U盘损坏了怎么办?

前言虽然一般来说引导U盘损坏的可能性很小,但是避免不了万一出现问题导致黑群晖没有办法引导进入系统也是一件相当麻烦的事情。这里我就用两块U盘做个小试验,看看如果黑群晖上的引导U盘损坏以后,另一块U盘需要怎样写引导文件才能让黑群晖正常引导进入系统。试验开始我这里黑群晖使用的是DSM6.1.7的系统,U盘一块使用的是闪迪的酷豆,另一块就是闪迪的酷铄。目前系统引导U盘使用的是酷豆,VID:0781 PID...

weixin_36239323的博客 8269

Error creating bean with name ‘authenticationManagerBean‘: Requested bean is currently in creation:

首先分析报错的日志,翻译过来很明显是提示我们:出现循环问题,可能是A和B互相调用了,又或者是对同一个服务的调用造成阻塞,anyway,出现的原因可以找到问题点,那就是bean出现循环引用了。我想原因可能是这样:在新增C服务之前,项目中的 A服务中的bean就已经注入了B服务中,现在新增的C服务也要注入A服务中的bean,在启动项目的时候,B服务已经启动,再来启动C服务,就会报错。在工作中碰到的一个有趣的小BUG,很有意思,涉及到springboot的自动注入知识。spring中的@Lazy注解。

momo牛的博客 1332

C++笔试题整理

目录 1. 笔试题1 1.1 链表反转 1.2 String 2. 笔试题2 2.1 求下面函数的返回值(微软) 2.2 什么是“引用”?申明和使用“引用”要注意哪些问题? 2.3 将“引用”作为函数参数有哪些特点? 2.4 在什么时候需要使用“常引用”?  2.5 将“引用”作为函数返回值类型的格式、好处和需要遵守的规则? 2.6 “引用”与多态的关系? 2.7 “引用”与指针的区别是什么? 2.8 什么时候需要“引用”? 2.9 结构与联合有和区别? 2.10 下面关于.

星月相随的专栏 2483

BeanCurrentlyInCreationException异常分析及解决

异常分析 Spring Boot 出现BeanCurrentlyInCreationException: Error creating bean with name: Requested bean is currently in creation异常是因为出现了两个bean相互依赖。如果 bean A依赖于bean B,而bean B又依赖于bean A,则将产生BeanCurrentlyInCreationException异常。 BEAN A -> BEAN B -> B...

skh2015java的博客 1万+

WinForm布局

登录模板页面UILoginForm

m0_71541781的博客 470

Verilog仿真时读取bin文件模拟输入数据流,将输出数据流写入bin文件

需要关注的是,一般会省略文件起始地址和读取长度,那么mem为多大,就会从文件中读取多大的数据出来填充mem。如果只需要读取一次文件,那么代码到此就结束了,但是如果还需要每一帧都读取该文件转换为数据流,则在循环里判断新的一帧信号是否到来,在新的一帧再次打开一次文件,从头开始读取数据。

qq_41137205的博客 2772

spring异常之BeanCreationNotAllowedException

BeanCreationNotAllowedException:遇到异常方不方?程序猿:慌毛线,我们跟着trace看一下 org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'stringRedisTemplate': Singleton bean cre...

阿呆的专栏 4万+

通信模组性能调优

本文介绍了高通平台通信模组性能调优的方法,主要包括硬件加速技术和CPU负载优化。针对CPU负载优化,提出了内核RPS/RFS功能启用、网卡队列调整、中断均衡、CPU性能模式设置等措施。同时建议关闭热管理并加强散热,调整TCP接收/发送缓存大小以解决TCP异常报文问题。这些优化手段可显著提高整机吞吐率测试中的网络性能表现。

四儿家的小祖宗的博客 1359

org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name

是一个常见的Spring异常,它提醒我们在Bean销毁时避免创建新的Bean实例。通过理解Bean的生命周期和Spring容器的关闭过程,我们可以采取适当的措施来避免这个异常,确保应用的稳定性和资源的正确管理。

赵KK的博客 6234

电路布局中近场耦合问题

开关电源EMC设计中,传导骚扰超标往往源于空间耦合而非参数问题。某案例中,DC-DC模块的非屏蔽电感磁场泄漏耦合到邻近X电容,导致0.5MHz频点超标。通过将X电容移至PCB底层、优化布局保持15mm间距后,问题完全解决。实践证明:EMC设计需注重空间隔离,优先采用屏蔽电感,滤波元件应远离高频磁场区,布局优化比参数调整更有效。这提示工程师需将电磁兼容视为空间问题而不仅是电气问题。

硬核科技 375

地平线旭日X3 安装xfce桌面+VNC查看USB摄像头

VNC是Virtual Network Computing的缩写,它是一种使用RFB(Remote Frame Buffer)协议的用于控制远程电脑的图形桌面分享系统。xfce桌面相比于GNOME桌面更加轻量,占用的资源更少,在没有GPU的设备上也可以运行(旭日的Desktop版本从外观上好像就是xfce桌面,具体没有尝试)。可以使用专用的VNC客户端连接到开发板,例如vnc viewer。板子默认带有openssh-server,因此,WiFi热点连接成功后,就可以使用ssh登录开发板了。

bingdund的博客 509

BeanCreationNotAllowedException

项目启动的时候报错:org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration': Singleton bean...

qq_39839828的博客 2681

Unity GameObject 核心机制深度解析:从底层结构到工程实践

从底层机制讲透 Unity GameObject:托管壳加原生芯的双层对象模型如何制造假 null 陷阱、Transform 层级与组件通信的原理、生命周期回调的确切顺序。文章同时给出 Instantiate 成本分析与对象池等高频场景的工程实践。

游戏人生 40

Spring 的循环依赖

前言记录Spring的一些基本理论,引申出Spring循环依赖的问题Spring是什么是容器(承载各种bean) 是基石、生态(SpringBoot、SpringCloud都是在此基础上的扩展)Spring容器(IOC)本质上就是一个Map,存放各种Bean整体工作流程BeanDefinitionReader 一个接口,约束和规范bean信息的定义。其子类是将各种格式的bean信息转换为BeanD...

天行健,君子以自强不息;地势坤,君子以厚德载物。 785

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

依赖注入底层反射原理_通过循环依赖解决你SpringIOC的所有疑惑

前言你可能想看Spring源码,却不知道应当如何入手去看,对整个Bean的流程又没有完整的概念。看过几遍源码,太多太复杂、没办法彻底理解,也没什么感觉,没过一阵子又忘了。结合这些问题接下来作者结合了多数实际问题,由问题引出源码,并在解释时会尽量以图表的形式让你一步一步彻底理解Spring Bean的IOC、DI、生命周期、作用域等。文章篇幅较长,请耐心观看,结尾有彩蛋哦!先看一个循环依赖问题现象循...

weixin_30914751的博客 171

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

从问题出发看Spring的对象创建与管理

本文探讨了Spring框架的核心特性——依赖注入(DI)及其背后的设计思想。作者以订单处理系统为例,指出传统new创建对象方式存在性能开销大、高耦合和生命周期管理混乱等问题。通过引入IoC容器和依赖注入机制,Spring实现了对象创建与使用的解耦。文章详细解析了Spring如何通过BeanDefinition获取管理对象,并重点阐述了应对复杂依赖关系的分段创建流程,包括缓存检查、实例创建、循环依赖处理、属性注入等关键步骤。这种设计有效解决了对象间的复杂依赖问题,使系统更灵活高效。

啾啾头号大粉丝打工买粮博客 974

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

彻底理解 SpringIOC、DI,这篇文章就够了

点击上方“方志朋”,选择“设为星标”回复”666“获取新整理的面试文章作者:lyowish收纳:JAVA葵花宝典链接:https://juejin.im/post/5be976a76fb9...

方志朋的博客 94

Spring核心机制全解析:从面试“炮灰“到技术“大神“的完美逆袭

这篇文章生动地描述了Java开发者面对Spring框架面试时的典型场景,通过对话形式引出Spring核心机制的学习重点。文章详细讲解了Spring Bean生命周期的关键概念和实现方式,包括:1)BeanPostProcessor的工作原理与自定义实现;2)InitializingBean与DisposableBean接口的使用;3)@PostConstruct/@PreDestroy注解的优雅实现;4)Bean实例化与初始化的区别。通过时序图和流程图直观展示了Bean的完整生命周期,并提供了具体代码示例。

weixin_54726354的博客 1024

Spring容器启动流程全解析:从面试“翻车“到技术“翻身“

Spring容器启动流程解析:从面试问题到核心技术 摘要:本文通过一个生动的面试场景引入,剖析了Spring容器启动的核心流程。首先展示了面试者常见的理解误区,随后详细解析了Spring容器启动的12个关键步骤,包括refresh()方法的源码实现、核心类关系图及启动时序图。重点内容包括:BeanFactory的创建与配置、BeanPostProcessor的注册机制、单例Bean的初始化流程,以及容器的生命周期管理。文章采用流程图、时序图等多种可视化方式,将复杂的启动过程分解为清晰的模块,帮助开发者深入理

weixin_54726354的博客 986

Spring Framework :IoC 容器的原理与实践

本文深入探讨了Spring框架中控制反转(IoC)容器的核心机制。文章首先分析了传统Java开发模式在对象管理上的局限性,进而阐述了IoC容器如何通过控制反转和依赖注入(DI)实现组件解耦。详细解析了IoC容器的核心组件(BeanFactory和ApplicationContext)及其三阶段工作流程(资源加载、Bean实例化、初始化)。同时介绍了三种配置方式(XML、注解、Java配置)的实践应用,并探讨了Bean作用域、循环依赖解决方案等进阶内容。最后提出了优先使用注解配置、依赖接口等最佳实践建议,帮助

sengminPark的博客 1356

Spring IOC 实现原理

软件系统中的组件耦合问题是一个常见的挑战,通常通过消息传递机制或控制反转机制来解决。本文聚焦于Java平台中基于控制反转机制的解耦合技术,特别是Spring的IOC容器。IOC(Inversion of Control)控制反转原则通过将组件的生命周期管理权交还给组件自身,减少依赖组件的变化对上游组件的影响。Spring IOC容器结合依赖注入、工厂模式和组件定位器模式,利用元数据配置、反射机制、代理模式等技术实现组件的生命周期管理、自动装配和定位。Spring IOC通过三级缓存体系和代理模式解决循环依赖

qj19842011的专栏 510

Spring IOC容器是如何解决循环依赖的问题?

什么是循环依赖? 先看代码: public class A { private B b; // 省略set/get方法 } public class B { private A a; // 省略set/get方法 } 可以看到A类里有一个属性是B类对象,而B类里也有一个属性是A类对象,则我们可以称A类对象与B类对象之间互相循环依赖。然后我们对把这俩个类纳入到IOC容器中进行管理,现在进行xml配置: <bean id="a" class="co..

libufan的博客 1306

Spring循环依赖

回过头来看看为什么要第三级缓存,而且为什么是工厂,而不是直接调用getEarlyBeanReference得到的代理对象。这是因为如果没有循环依赖的话,工厂根本不会被调用,没必要提早生成这个代理对象,只需要按原来的流程,在initializeBean正常生成代理对象即可。然后为什么需要第二级缓存,之前已经说了,存放还没完全创建好的bean呗。

qq_36769368的博客 4434

spring解决循环依赖

前言 你可能会有如下问题: 1、想看Spring源码,但是不知道应当如何入手去看,对整个Bean的流程没有概念,碰到相关问题也没有头绪如何下手 2、看过几遍源码,没办法彻底理解,没什么感觉,没过一阵子又忘了 本文将结合实际问题,由问题引出源码,并在解释时会尽量以图表的形式让你一步一步彻底理解Spring Bean的IOC、DI、生命周期、作用域等。 先看一个循环依赖问题 现象 循...

zcywell的专栏 3317

Spring IOC 如何解决循环依赖?

前言 假设对象A、B 之间相互依赖,Spring IOC是如何解决A、B两个对象的实例化的?答案是三级缓存。 三级缓存 SpringIOC 通过三级缓存来解决循环依赖问题,三级缓存指的是三个Map: singletonObjects:一级缓存,key为BeanName,value为Bean,日常获取Bean的地方 earlySingletonObjects:二级缓存,key为BeanName,value为Bean,已经实例化但还没有进行属性注入的Bean,由三级缓存放入 singletonFactorie

weixin_43966635的博客 4857

小心@Async注解,让我们进入Spring循环依赖的坑

早期暴露出去的对象,可能是 AService 本身或者是 AService 的代理对象,而且是通过 AnnotationAwareAspectJAutoProxyCreator 对象实现的,但是通过 AsyncAnnotationBeanPostProcessor 的回调,会对 AService 对象进行动态代理,这就导致 AService 早期暴露出去的对象跟最后完全创造出来的对象不是同一个,那么肯定就不对了。也就说,AOP 和 @Async 注解虽然底层都是动态代理,但是具体实现的类是不一样的。

LoveSummer 5万+
上一篇: oracle 启动 命令
下一篇: ibatis iterator list 参数 查询
xiaoxinphp
博客等级 码龄18年 1粉丝 45原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值