Force initialization of configuration class in mainline thread

Closes gh-36844
This commit is contained in:
Juergen Hoeller
2026-05-27 16:32:37 +02:00
parent 121c0ac285
commit af2b96192d
2 changed files with 49 additions and 0 deletions
@@ -1154,12 +1154,19 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
if (mbd.isBackgroundInit()) {
Executor executor = getBootstrapExecutor();
if (executor != null) {
// Force initialization of depends-on beans in mainline thread.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
getBean(dep);
}
}
// Force initialization of factory reference in mainline thread.
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
getBean(factoryBeanName);
}
// Instantiate current bean in background thread.
CompletableFuture<?> future = CompletableFuture.runAsync(
() -> instantiateSingletonInBackgroundThread(beanName), executor);
addSingletonFactory(beanName, () -> {
@@ -197,6 +197,16 @@ class BackgroundBootstrapTests {
}
}
@Test
@Timeout(10)
@EnabledForTestGroups(LONG_RUNNING)
void bootstrapWithCustomExecutorAndLazyConfig() {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(CustomExecutorLazyBeanConfig.class);
assertThat(ctx.getBeanFactory().containsSingleton("testBean1")).isTrue();
assertThat(ctx.getBeanFactory().containsSingleton("testBean2")).isTrue();
ctx.close();
}
@Configuration(proxyBeanMethods = false)
static class UnmanagedThreadBeanConfig {
@@ -542,4 +552,36 @@ class BackgroundBootstrapTests {
}
}
@Configuration(proxyBeanMethods = false)
static class CustomExecutorLazyBeanConfig {
@Bean
public ThreadPoolTaskExecutor bootstrapExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setThreadNamePrefix("Custom-");
executor.setCorePoolSize(2);
executor.initialize();
return executor;
}
@Configuration(proxyBeanMethods = false)
@Lazy
static class LazyBeanConfig {
@Bean(bootstrap = BACKGROUND)
public TestBean testBean1() throws InterruptedException {
Thread.sleep(6000);
return new TestBean();
}
@Bean(bootstrap = BACKGROUND)
@Lazy
public TestBean testBean2() throws InterruptedException {
Thread.sleep(6000);
return new TestBean();
}
}
}
}