Skip to content

Commit 121be15

Browse files
committed
Merge branch '6.2.x'
2 parents 7405e20 + 323e52b commit 121be15

File tree

2 files changed

+53
-4
lines changed

2 files changed

+53
-4
lines changed

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -1072,8 +1072,15 @@ else if (logger.isInfoEnabled()) {
10721072
"without bootstrap executor configured - falling back to mainline initialization");
10731073
}
10741074
}
1075+
10751076
if (!mbd.isLazyInit()) {
1076-
instantiateSingleton(beanName);
1077+
try {
1078+
instantiateSingleton(beanName);
1079+
}
1080+
catch (BeanCurrentlyInCreationException ex) {
1081+
logger.info("Bean '" + beanName + "' marked for pre-instantiation (not lazy-init) " +
1082+
"but currently initialized by other thread - skipping it in mainline thread");
1083+
}
10771084
}
10781085
return null;
10791086
}

Diff for: spring-context/src/test/java/org/springframework/context/annotation/BackgroundBootstrapTests.java

+45-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,11 +19,14 @@
1919
import org.junit.jupiter.api.Test;
2020
import org.junit.jupiter.api.Timeout;
2121

22+
import org.springframework.beans.factory.BeanCurrentlyInCreationException;
23+
import org.springframework.beans.factory.ObjectProvider;
2224
import org.springframework.beans.testfixture.beans.TestBean;
2325
import org.springframework.context.ConfigurableApplicationContext;
2426
import org.springframework.core.testfixture.EnabledForTestGroups;
2527
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
2628

29+
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
2730
import static org.springframework.context.annotation.Bean.Bootstrap.BACKGROUND;
2831
import static org.springframework.core.testfixture.TestGroup.LONG_RUNNING;
2932

@@ -33,6 +36,17 @@
3336
*/
3437
class BackgroundBootstrapTests {
3538

39+
@Test
40+
@Timeout(5)
41+
@EnabledForTestGroups(LONG_RUNNING)
42+
void bootstrapWithUnmanagedThread() {
43+
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(UnmanagedThreadBeanConfig.class);
44+
ctx.getBean("testBean1", TestBean.class);
45+
assertThatExceptionOfType(BeanCurrentlyInCreationException.class).isThrownBy( // late - not during refresh
46+
() -> ctx.getBean("testBean2", TestBean.class));
47+
ctx.close();
48+
}
49+
3650
@Test
3751
@Timeout(5)
3852
@EnabledForTestGroups(LONG_RUNNING)
@@ -45,7 +59,35 @@ void bootstrapWithCustomExecutor() {
4559
}
4660

4761

48-
@Configuration
62+
@Configuration(proxyBeanMethods = false)
63+
static class UnmanagedThreadBeanConfig {
64+
65+
@Bean
66+
public TestBean testBean1(ObjectProvider<TestBean> testBean2) {
67+
new Thread(testBean2::getObject).start();
68+
try {
69+
Thread.sleep(1000);
70+
}
71+
catch (InterruptedException ex) {
72+
throw new RuntimeException(ex);
73+
}
74+
return new TestBean();
75+
}
76+
77+
@Bean
78+
public TestBean testBean2() {
79+
try {
80+
Thread.sleep(2000);
81+
}
82+
catch (InterruptedException ex) {
83+
throw new RuntimeException(ex);
84+
}
85+
return new TestBean();
86+
}
87+
}
88+
89+
90+
@Configuration(proxyBeanMethods = false)
4991
static class CustomExecutorBeanConfig {
5092

5193
@Bean
@@ -58,7 +100,7 @@ public ThreadPoolTaskExecutor bootstrapExecutor() {
58100
}
59101

60102
@Bean(bootstrap = BACKGROUND) @DependsOn("testBean3")
61-
public TestBean testBean1(TestBean testBean3) throws InterruptedException{
103+
public TestBean testBean1(TestBean testBean3) throws InterruptedException {
62104
Thread.sleep(3000);
63105
return new TestBean();
64106
}

0 commit comments

Comments
 (0)