Browse Source

Try late locking for waiting on specific bean to be finished

Closes gh-34186
pull/34398/head
Juergen Hoeller 11 months ago
parent
commit
467d5f3ca3
  1. 22
      spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java
  2. 6
      spring-beans/src/test/java/org/springframework/beans/factory/BeanFactoryLockingTests.java

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

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -279,7 +279,25 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements @@ -279,7 +279,25 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);
try {
beforeSingletonCreation(beanName);
}
catch (BeanCurrentlyInCreationException ex) {
if (locked) {
throw ex;
}
// Try late locking for waiting on specific bean to be finished.
this.singletonLock.lock();
locked = true;
// Singleton object should have appeared in the meantime.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject != null) {
return singletonObject;
}
beforeSingletonCreation(beanName);
}
boolean newSingleton = false;
boolean recordSuppressedExceptions = (locked && this.suppressedExceptions == null);
if (recordSuppressedExceptions) {

6
spring-beans/src/test/java/org/springframework/beans/factory/BeanFactoryLockingTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,7 +23,6 @@ import org.springframework.beans.factory.support.RootBeanDefinition; @@ -23,7 +23,6 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.testfixture.beans.TestBean;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* @author Juergen Hoeller
@ -56,9 +55,6 @@ class BeanFactoryLockingTests { @@ -56,9 +55,6 @@ class BeanFactoryLockingTests {
@Override
public void afterPropertiesSet() throws Exception {
Thread thread = new Thread(() -> {
// Fail for circular reference from other thread
assertThatExceptionOfType(BeanCurrentlyInCreationException.class).isThrownBy(() ->
beanFactory.getBean(ThreadDuringInitialization.class));
// Leniently create unrelated other bean outside of singleton lock
assertThat(beanFactory.getBean(TestBean.class).getName()).isEqualTo("tb");
// Creation attempt in other thread was successful

Loading…
Cancel
Save