Spring Bean Lifecycle: Detailed Process Flow and Code Explanation
This article provides a comprehensive walkthrough of the Spring Bean lifecycle, covering bean retrieval, creation, property population, initialization, and destruction, illustrated with flowcharts and extensive Java code snippets from the AbstractBeanFactory and AbstractAutowireCapableBeanFactory classes.
Spring's Bean lifecycle is a multi‑stage process that begins with bean retrieval, proceeds through creation, property population, initialization, and ends with destruction. The article first outlines the entry point of bean acquisition in AbstractBeanFactory.doGetBean, describing how bean names are processed, singleton caches are checked, and circular dependencies are resolved.
1. Getting the Bean
The flow starts at AbstractBeanFactory.doGetBean. It handles special bean names prefixed with '&', checks the singleton cache, and if not found, resolves parent factories or merges definitions before creating the bean.
2. Creating the Bean
2.1 Before Instantiation
The method AbstractAutowireCapableBeanFactory.createBean checks several conditions: whether beforeInstantiationResolved is true, whether the bean is a native bean, and whether it has InstantiationAwareBeanPostProcessor s. If all are satisfied, it invokes postProcessBeforeInstantiation and possibly postProcessAfterInitialization.
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
// condition 1
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// condition 2 & 3
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
}
return bean;
}2.1.1 Bean Instantiation (createBeanInstance)
The actual instantiation logic resides in createBeanInstance. It resolves the bean class, checks visibility, handles instance suppliers, factory methods, and constructor autowiring.
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// further constructor resolution logic omitted for brevity
return null;
}2.1.2 Property Population (populateBean)
After instantiation, populateBean applies property values, handling autowiring by name or type, and invoking InstantiationAwareBeanPostProcessor s for post‑processing.
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Cannot apply property values to null instance");
}
return;
}
// Autowire by name/type, apply post‑processors, dependency checks, etc.
// ... (code omitted for brevity)
}2.1.3 Initialization (initializeBean)
During initialization, the bean may implement various *Aware interfaces. The ApplicationContextAwareProcessor invokes methods for EnvironmentAware, ResourceLoaderAware, ApplicationContextAware, etc. BeanPostProcessors' postProcessBeforeInitialization and postProcessAfterInitialization are also called.
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// ... other setup ...
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// ...
}3. Destruction
When the container shuts down, Spring checks for a custom destroy method or a DestructionAwareBeanPostProcessor. It registers a DisposableBeanAdapter that will invoke the appropriate destroy logic.
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
// ...
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
// ...
} public void destroy() {
if (this.invokeDisposableBean) {
try {
((DisposableBean) this.bean).destroy();
} catch (Throwable ex) {
// log warning
}
}
// invoke custom destroy method if defined
}4. Summary
The article concludes with a series of flowcharts that visualize the entire lifecycle: pre‑instantiation preparation, actual instantiation, post‑instantiation processing, initialization, and final destruction. These diagrams help readers understand the intricate steps Spring performs behind the scenes when managing beans.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architecture Digest
Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
