Browse Source

Wait for lenient bean creation in non-locked threads as well

Closes gh-34349
pull/34656/head
Juergen Hoeller 1 year ago
parent
commit
dfc10c1a8d
  1. 37
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java
  2. 2
      spring-context/src/test/java/org/springframework/context/annotation/BackgroundBootstrapTests.java

37
spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

@ -303,26 +303,29 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
beforeSingletonCreation(beanName); beforeSingletonCreation(beanName);
} }
catch (BeanCurrentlyInCreationException ex) { catch (BeanCurrentlyInCreationException ex) {
if (locked) { this.lenientCreationLock.lock();
this.lenientCreationLock.lock(); try {
try { while ((singletonObject = this.singletonObjects.get(beanName)) == null) {
while ((singletonObject = this.singletonObjects.get(beanName)) == null) { if (!this.singletonsInLenientCreation.contains(beanName)) {
if (!this.singletonsInLenientCreation.contains(beanName)) { break;
throw ex; }
} try {
try { this.lenientCreationFinished.await();
this.lenientCreationFinished.await(); }
} catch (InterruptedException ie) {
catch (InterruptedException ie) { Thread.currentThread().interrupt();
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. // Try late locking for waiting on specific bean to be finished.
this.singletonLock.lock(); this.singletonLock.lock();
locked = true; locked = true;

2
spring-context/src/test/java/org/springframework/context/annotation/BackgroundBootstrapTests.java

@ -102,6 +102,8 @@ class BackgroundBootstrapTests {
@Bean @Bean
public TestBean testBean1(ObjectProvider<TestBean> testBean3, ObjectProvider<TestBean> testBean4) { public TestBean testBean1(ObjectProvider<TestBean> testBean3, ObjectProvider<TestBean> testBean4) {
new Thread(testBean3::getObject).start();
new Thread(testBean4::getObject).start();
new Thread(testBean3::getObject).start(); new Thread(testBean3::getObject).start();
new Thread(testBean4::getObject).start(); new Thread(testBean4::getObject).start();
try { try {

Loading…
Cancel
Save