Mark bootstrap thread for entire finishBeanFactoryInitialization phase
Backport Bot / build (push) Has been cancelled
Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:25], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled
Details
Deploy Docs / Dispatch docs deployment (push) Has been cancelled
Details
Build and Deploy Snapshot / Verify (push) Has been cancelled
Details
Backport Bot / build (push) Has been cancelled
Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:21], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:25], map[id:ubuntu-latest name:Linux]) (push) Has been cancelled
Details
Deploy Docs / Dispatch docs deployment (push) Has been cancelled
Details
Build and Deploy Snapshot / Verify (push) Has been cancelled
Details
Closes gh-35398
This commit is contained in:
parent
ecd3dd8883
commit
80e7ee321e
|
@ -152,6 +152,18 @@ public interface ConfigurableListableBeanFactory
|
|||
*/
|
||||
boolean isConfigurationFrozen();
|
||||
|
||||
/**
|
||||
* Mark current thread as main bootstrap thread for singleton instantiation,
|
||||
* with lenient bootstrap locking applying for background threads.
|
||||
* <p>Any such marker is to be removed at the end of the managed bootstrap in
|
||||
* {@link #preInstantiateSingletons()}.
|
||||
* @since 6.2.12
|
||||
* @see #setBootstrapExecutor
|
||||
* @see #preInstantiateSingletons()
|
||||
*/
|
||||
default void prepareSingletonBootstrap() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that all non-lazy-init singletons are instantiated, also considering
|
||||
* {@link org.springframework.beans.factory.FactoryBean FactoryBeans}.
|
||||
|
@ -159,6 +171,7 @@ public interface ConfigurableListableBeanFactory
|
|||
* @throws BeansException if one of the singleton beans could not be created.
|
||||
* Note: This may have left the factory with some beans already initialized!
|
||||
* Call {@link #destroySingletons()} for full cleanup in this case.
|
||||
* @see #prepareSingletonBootstrap()
|
||||
* @see #destroySingletons()
|
||||
*/
|
||||
void preInstantiateSingletons() throws BeansException;
|
||||
|
|
|
@ -1102,6 +1102,11 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareSingletonBootstrap() {
|
||||
this.mainThreadPrefix = getThreadNamePrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preInstantiateSingletons() throws BeansException {
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
@ -1114,7 +1119,9 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
|||
|
||||
// Trigger initialization of all non-lazy singleton beans...
|
||||
this.preInstantiationThread.set(PreInstantiation.MAIN);
|
||||
if (this.mainThreadPrefix == null) {
|
||||
this.mainThreadPrefix = getThreadNamePrefix();
|
||||
}
|
||||
try {
|
||||
List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||
for (String beanName : beanNames) {
|
||||
|
|
|
@ -936,6 +936,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
|||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
|
||||
// Mark current thread for singleton instantiation with applied bootstrap locking.
|
||||
beanFactory.prepareSingletonBootstrap();
|
||||
|
||||
// Initialize bootstrap executor for this context.
|
||||
if (beanFactory.containsBean(BOOTSTRAP_EXECUTOR_BEAN_NAME) &&
|
||||
beanFactory.isTypeMatch(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class)) {
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
|||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.weaving.LoadTimeWeaverAware;
|
||||
import org.springframework.core.SpringProperties;
|
||||
import org.springframework.core.testfixture.EnabledForTestGroups;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
@ -68,6 +69,16 @@ class BackgroundBootstrapTests {
|
|||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timeout(10)
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
void bootstrapWithLoadTimeWeaverAware() {
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(LoadTimeWeaverAwareBeanConfig.class);
|
||||
ctx.getBean("testBean1", TestBean.class);
|
||||
ctx.getBean("testBean2", TestBean.class);
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Timeout(10)
|
||||
@EnabledForTestGroups(LONG_RUNNING)
|
||||
|
@ -266,6 +277,50 @@ class BackgroundBootstrapTests {
|
|||
}
|
||||
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class LoadTimeWeaverAwareBeanConfig {
|
||||
|
||||
@Bean
|
||||
LoadTimeWeaverAware loadTimeWeaverAware(ObjectProvider<TestBean> testBean1) {
|
||||
Thread thread = new Thread(testBean1::getObject);
|
||||
thread.start();
|
||||
try {
|
||||
thread.join();
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
return (loadTimeWeaver -> {});
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestBean testBean1(TestBean testBean2) {
|
||||
return new TestBean(testBean2);
|
||||
}
|
||||
|
||||
@Bean @Lazy
|
||||
public FactoryBean<TestBean> testBean2() {
|
||||
try {
|
||||
Thread.sleep(2000);
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
TestBean testBean = new TestBean();
|
||||
return new FactoryBean<>() {
|
||||
@Override
|
||||
public TestBean getObject() {
|
||||
return testBean;
|
||||
}
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return testBean.getClass();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class StrictLockingBeanConfig {
|
||||
|
||||
|
|
Loading…
Reference in New Issue