From dfc10c1a8d2784823a8418ee649d6080fc895add Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 12 Feb 2025 23:06:22 +0100 Subject: [PATCH] Wait for lenient bean creation in non-locked threads as well Closes gh-34349 --- .../support/DefaultSingletonBeanRegistry.java | 37 ++++++++++--------- .../annotation/BackgroundBootstrapTests.java | 2 + 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java index 27ad39ee3afc..835be3e501fa 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java @@ -303,26 +303,29 @@ public Object getSingleton(String beanName, ObjectFactory singletonFactory) { beforeSingletonCreation(beanName); } catch (BeanCurrentlyInCreationException ex) { - if (locked) { - this.lenientCreationLock.lock(); - try { - while ((singletonObject = this.singletonObjects.get(beanName)) == null) { - if (!this.singletonsInLenientCreation.contains(beanName)) { - throw ex; - } - try { - this.lenientCreationFinished.await(); - } - catch (InterruptedException ie) { - Thread.currentThread().interrupt(); - } + this.lenientCreationLock.lock(); + try { + while ((singletonObject = this.singletonObjects.get(beanName)) == null) { + if (!this.singletonsInLenientCreation.contains(beanName)) { + break; + } + try { + this.lenientCreationFinished.await(); + } + catch (InterruptedException ie) { + Thread.currentThread().interrupt(); } - return singletonObject; - } - finally { - this.lenientCreationLock.unlock(); } } + finally { + this.lenientCreationLock.unlock(); + } + if (singletonObject != null) { + return singletonObject; + } + if (locked) { + throw ex; + } // Try late locking for waiting on specific bean to be finished. this.singletonLock.lock(); locked = true; diff --git a/spring-context/src/test/java/org/springframework/context/annotation/BackgroundBootstrapTests.java b/spring-context/src/test/java/org/springframework/context/annotation/BackgroundBootstrapTests.java index ec186e4ccd86..c95f930d92ca 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/BackgroundBootstrapTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/BackgroundBootstrapTests.java @@ -102,6 +102,8 @@ static class UnmanagedThreadsBeanConfig { @Bean public TestBean testBean1(ObjectProvider testBean3, ObjectProvider testBean4) { + new Thread(testBean3::getObject).start(); + new Thread(testBean4::getObject).start(); new Thread(testBean3::getObject).start(); new Thread(testBean4::getObject).start(); try {