Skip to content

Commit af2b961

Browse files
committed
Force initialization of configuration class in mainline thread
Closes gh-36844
1 parent 121c0ac commit af2b961

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,12 +1154,19 @@ public void preInstantiateSingletons() throws BeansException {
11541154
if (mbd.isBackgroundInit()) {
11551155
Executor executor = getBootstrapExecutor();
11561156
if (executor != null) {
1157+
// Force initialization of depends-on beans in mainline thread.
11571158
String[] dependsOn = mbd.getDependsOn();
11581159
if (dependsOn != null) {
11591160
for (String dep : dependsOn) {
11601161
getBean(dep);
11611162
}
11621163
}
1164+
// Force initialization of factory reference in mainline thread.
1165+
String factoryBeanName = mbd.getFactoryBeanName();
1166+
if (factoryBeanName != null) {
1167+
getBean(factoryBeanName);
1168+
}
1169+
// Instantiate current bean in background thread.
11631170
CompletableFuture<?> future = CompletableFuture.runAsync(
11641171
() -> instantiateSingletonInBackgroundThread(beanName), executor);
11651172
addSingletonFactory(beanName, () -> {

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,16 @@ void bootstrapWithCustomExecutorAndStrictLocking() {
197197
}
198198
}
199199

200+
@Test
201+
@Timeout(10)
202+
@EnabledForTestGroups(LONG_RUNNING)
203+
void bootstrapWithCustomExecutorAndLazyConfig() {
204+
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(CustomExecutorLazyBeanConfig.class);
205+
assertThat(ctx.getBeanFactory().containsSingleton("testBean1")).isTrue();
206+
assertThat(ctx.getBeanFactory().containsSingleton("testBean2")).isTrue();
207+
ctx.close();
208+
}
209+
200210

201211
@Configuration(proxyBeanMethods = false)
202212
static class UnmanagedThreadBeanConfig {
@@ -542,4 +552,36 @@ public TestBean testBean4(@Lazy TestBean testBean1, @Lazy TestBean testBean2, @L
542552
}
543553
}
544554

555+
556+
@Configuration(proxyBeanMethods = false)
557+
static class CustomExecutorLazyBeanConfig {
558+
559+
@Bean
560+
public ThreadPoolTaskExecutor bootstrapExecutor() {
561+
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
562+
executor.setThreadNamePrefix("Custom-");
563+
executor.setCorePoolSize(2);
564+
executor.initialize();
565+
return executor;
566+
}
567+
568+
@Configuration(proxyBeanMethods = false)
569+
@Lazy
570+
static class LazyBeanConfig {
571+
572+
@Bean(bootstrap = BACKGROUND)
573+
public TestBean testBean1() throws InterruptedException {
574+
Thread.sleep(6000);
575+
return new TestBean();
576+
}
577+
578+
@Bean(bootstrap = BACKGROUND)
579+
@Lazy
580+
public TestBean testBean2() throws InterruptedException {
581+
Thread.sleep(6000);
582+
return new TestBean();
583+
}
584+
}
585+
}
586+
545587
}

0 commit comments

Comments
 (0)