Avoid early singleton inference outside of original creation thread
See gh-23501
This commit is contained in:
parent
902e5707a8
commit
4a02893c31
|
|
@ -188,7 +188,10 @@ public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements
|
|||
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
|
||||
singletonObject = this.earlySingletonObjects.get(beanName);
|
||||
if (singletonObject == null && allowEarlyReference) {
|
||||
this.singletonLock.lock();
|
||||
if (!this.singletonLock.tryLock()) {
|
||||
// Avoid early singleton inference outside of original creation thread
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
// Consistent creation of early reference within full singleton lock
|
||||
singletonObject = this.singletonObjects.get(beanName);
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
|||
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
|
||||
* @since 6.2
|
||||
|
|
@ -31,8 +34,10 @@ class BeanFactoryLockingTests {
|
|||
@Test
|
||||
void fallbackForThreadDuringInitialization() {
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
beanFactory.registerBeanDefinition("bean1", new RootBeanDefinition(ThreadDuringInitialization.class));
|
||||
beanFactory.registerBeanDefinition("bean2", new RootBeanDefinition(TestBean.class));
|
||||
beanFactory.registerBeanDefinition("bean1",
|
||||
new RootBeanDefinition(ThreadDuringInitialization.class));
|
||||
beanFactory.registerBeanDefinition("bean2",
|
||||
new RootBeanDefinition(TestBean.class, () -> new TestBean("tb")));
|
||||
beanFactory.getBean(ThreadDuringInitialization.class);
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +56,12 @@ class BeanFactoryLockingTests {
|
|||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Thread thread = new Thread(() -> {
|
||||
beanFactory.getBean(TestBean.class);
|
||||
// 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
|
||||
initialized = true;
|
||||
});
|
||||
thread.start();
|
||||
|
|
|
|||
Loading…
Reference in New Issue