Introduce background bootstrapping for individual singleton beans
Closes gh-13410 Closes gh-19487 See gh-23501
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.context;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
@@ -53,6 +54,16 @@ public interface ConfigurableApplicationContext extends ApplicationContext, Life
|
||||
*/
|
||||
String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
|
||||
|
||||
/**
|
||||
* The name of the {@link Executor bootstrap executor} bean in the context.
|
||||
* If none is supplied, no background bootstrapping will be active.
|
||||
* @since 6.2
|
||||
* @see java.util.concurrent.Executor
|
||||
* @see org.springframework.core.task.TaskExecutor
|
||||
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#setBootstrapExecutor
|
||||
*/
|
||||
String BOOTSTRAP_EXECUTOR_BEAN_NAME = "bootstrapExecutor";
|
||||
|
||||
/**
|
||||
* Name of the ConversionService bean in the factory.
|
||||
* If none is supplied, default conversion rules apply.
|
||||
|
||||
@@ -260,6 +260,20 @@ public @interface Bean {
|
||||
*/
|
||||
boolean defaultCandidate() default true;
|
||||
|
||||
/**
|
||||
* The bootstrap mode for this bean: default is the main pre-instantiation thread
|
||||
* for non-lazy singleton beans and the caller thread for prototype beans.
|
||||
* <p>Set {@link Bootstrap#BACKGROUND} to allow for instantiating this bean on a
|
||||
* background thread. For a non-lazy singleton, a background pre-instantiation
|
||||
* thread can be used then, while still enforcing the completion at the end of
|
||||
* {@link org.springframework.context.ConfigurableApplicationContext#refresh()}.
|
||||
* For a lazy singleton, a background pre-instantiation thread can be used as well
|
||||
* - with completion allowed at a later point, enforcing it when actually accessed.
|
||||
* @since 6.2
|
||||
* @see Lazy
|
||||
*/
|
||||
Bootstrap bootstrap() default Bootstrap.DEFAULT;
|
||||
|
||||
/**
|
||||
* The optional name of a method to call on the bean instance during initialization.
|
||||
* Not commonly used, given that the method may be called programmatically directly
|
||||
@@ -299,4 +313,28 @@ public @interface Bean {
|
||||
*/
|
||||
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
|
||||
|
||||
|
||||
/**
|
||||
* Local enumeration for the bootstrap mode.
|
||||
* @since 6.2
|
||||
* @see #bootstrap()
|
||||
*/
|
||||
enum Bootstrap {
|
||||
|
||||
/**
|
||||
* Constant to indicate the main pre-instantiation thread for non-lazy
|
||||
* singleton beans and the caller thread for prototype beans.
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
/**
|
||||
* Allow for instantiating a bean on a background thread.
|
||||
* <p>For a non-lazy singleton, a background pre-instantiation thread
|
||||
* can be used while still enforcing the completion on context refresh.
|
||||
* For a lazy singleton, a background pre-instantiation thread can be used
|
||||
* with completion allowed at a later point (when actually accessed).
|
||||
*/
|
||||
BACKGROUND,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -251,6 +251,11 @@ class ConfigurationClassBeanDefinitionReader {
|
||||
beanDef.setDefaultCandidate(false);
|
||||
}
|
||||
|
||||
Bean.Bootstrap instantiation = bean.getEnum("bootstrap");
|
||||
if (instantiation == Bean.Bootstrap.BACKGROUND) {
|
||||
beanDef.setBackgroundInit(true);
|
||||
}
|
||||
|
||||
String initMethodName = bean.getString("initMethod");
|
||||
if (StringUtils.hasText(initMethodName)) {
|
||||
beanDef.setInitMethodName(initMethodName);
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -137,17 +138,6 @@ import org.springframework.util.ReflectionUtils;
|
||||
public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
implements ConfigurableApplicationContext {
|
||||
|
||||
/**
|
||||
* The name of the {@link LifecycleProcessor} bean in the context.
|
||||
* If none is supplied, a {@link DefaultLifecycleProcessor} is used.
|
||||
* @since 3.0
|
||||
* @see org.springframework.context.LifecycleProcessor
|
||||
* @see org.springframework.context.support.DefaultLifecycleProcessor
|
||||
* @see #start()
|
||||
* @see #stop()
|
||||
*/
|
||||
public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";
|
||||
|
||||
/**
|
||||
* The name of the {@link MessageSource} bean in the context.
|
||||
* If none is supplied, message resolution is delegated to the parent.
|
||||
@@ -168,6 +158,17 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
*/
|
||||
public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
|
||||
|
||||
/**
|
||||
* The name of the {@link LifecycleProcessor} bean in the context.
|
||||
* If none is supplied, a {@link DefaultLifecycleProcessor} is used.
|
||||
* @since 3.0
|
||||
* @see org.springframework.context.LifecycleProcessor
|
||||
* @see org.springframework.context.support.DefaultLifecycleProcessor
|
||||
* @see #start()
|
||||
* @see #stop()
|
||||
*/
|
||||
public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";
|
||||
|
||||
|
||||
static {
|
||||
// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
|
||||
@@ -806,8 +807,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the MessageSource.
|
||||
* Use parent's if none defined in this context.
|
||||
* Initialize the {@link MessageSource}.
|
||||
* <p>Uses parent's {@code MessageSource} if none defined in this context.
|
||||
* @see #MESSAGE_SOURCE_BEAN_NAME
|
||||
*/
|
||||
protected void initMessageSource() {
|
||||
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
|
||||
@@ -837,8 +839,9 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the ApplicationEventMulticaster.
|
||||
* Uses SimpleApplicationEventMulticaster if none defined in the context.
|
||||
* Initialize the {@link ApplicationEventMulticaster}.
|
||||
* <p>Uses {@link SimpleApplicationEventMulticaster} if none defined in the context.
|
||||
* @see #APPLICATION_EVENT_MULTICASTER_BEAN_NAME
|
||||
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
|
||||
*/
|
||||
protected void initApplicationEventMulticaster() {
|
||||
@@ -861,15 +864,16 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the LifecycleProcessor.
|
||||
* Uses DefaultLifecycleProcessor if none defined in the context.
|
||||
* Initialize the {@link LifecycleProcessor}.
|
||||
* <p>Uses {@link DefaultLifecycleProcessor} if none defined in the context.
|
||||
* @since 3.0
|
||||
* @see #LIFECYCLE_PROCESSOR_BEAN_NAME
|
||||
* @see org.springframework.context.support.DefaultLifecycleProcessor
|
||||
*/
|
||||
protected void initLifecycleProcessor() {
|
||||
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
|
||||
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
|
||||
this.lifecycleProcessor =
|
||||
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
|
||||
this.lifecycleProcessor = beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
|
||||
}
|
||||
@@ -929,6 +933,13 @@ public abstract class AbstractApplicationContext extends DefaultResourceLoader
|
||||
* initializing all remaining singleton beans.
|
||||
*/
|
||||
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
|
||||
// Initialize bootstrap executor for this context.
|
||||
if (beanFactory.containsBean(BOOTSTRAP_EXECUTOR_BEAN_NAME) &&
|
||||
beanFactory.isTypeMatch(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class)) {
|
||||
beanFactory.setBootstrapExecutor(
|
||||
beanFactory.getBean(BOOTSTRAP_EXECUTOR_BEAN_NAME, Executor.class));
|
||||
}
|
||||
|
||||
// Initialize conversion service for this context.
|
||||
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
|
||||
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
|
||||
|
||||
Reference in New Issue
Block a user