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