Understanding the Full Lifecycle of Spring Beans: From Instantiation to Destruction

This article walks through every stage of a Spring Bean's lifecycle—including instantiation, property population, initialization callbacks, usage, and destruction—while providing concrete code examples, execution traces, and an analysis of the underlying Spring source methods.

Shepherd Advanced Notes
Shepherd Advanced Notes
Shepherd Advanced Notes
Understanding the Full Lifecycle of Spring Beans: From Instantiation to Destruction

1. Overview of the Bean Lifecycle

Spring manages Java objects as beans, creating and controlling them through the IoC container. The lifecycle consists of five main phases: Instantiation, Property Population, Initialization (including Aware callbacks, BeanPostProcessor hooks, InitializingBean, and custom init methods), Usage, and Destruction (via destroy-method or DisposableBean).

2. Detailed Lifecycle Walk‑through and Example

The article corrects a common misconception: only BeanPostProcessor participates in the bean lifecycle, while BeanDefinitionRegistryPostProcessor and BeanFactoryPostProcessor operate on bean definitions.

A sample bean Boo implements several lifecycle interfaces and defines @PostConstruct and @PreDestroy methods. The following code demonstrates the bean definition:

@Data
@AllArgsConstructor
public class Boo implements InitializingBean, DisposableBean, BeanNameAware {
    private Long id;
    private String name;

    public Boo() {
        System.out.println("boo实例化构造方法执行了...");
    }

    @PostConstruct
    public void initMethod() {
        System.out.println("boo执行初始化init()方法了...");
    }

    @PreDestroy
    public void destroyMethod() {
        System.out.println("boo执行初始化destroy()方法了...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("boo执行InitializingBean的afterPropertiesSet()方法了...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("boo执行DisposableBean的destroy()方法了...");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("boo执行BeanNameAware的setBeanName()方法了...");
    }
}

Two custom post‑processors are provided to illustrate the callback order:

@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor的before()执行了...." + beanName);
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("InstantiationAwareBeanPostProcessor的after()执行了...." + beanName);
        return false;
    }
}

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor的before()执行了...." + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor的after()执行了...." + beanName);
        return bean;
    }
}

The configuration class creates the bean and closes the context, triggering the full sequence of callbacks. The console output confirms the exact order, matching the diagram shown earlier:

InstantiationAwareBeanPostProcessor的before()执行了....boo
boo实例化构造方法执行了...
InstantiationAwareBeanPostProcessor的after()执行了....boo
boo执行BeanNameAware的setBeanName()方法了...
BeanPostProcessor的before()执行了....boo
boo执行初始化init()方法了...
boo执行InitializingBean的afterPropertiesSet()方法了...
BeanPostProcessor的after()执行了....boo
...
boo执行初始化destroy()方法了...
boo执行DisposableBean的destroy()方法了...

Closing the ApplicationContext invokes the destruction callbacks, demonstrating that the lifecycle is fully controlled by the container.

3. Source‑Code Deep Dive

The core creation logic resides in DefaultListableBeanFactoryAbstractAutowireCapableBeanFactory#doCreateBean(). The method performs the following steps (numbers correspond to comments in the original source):

Instantiate the bean via createBeanInstance().

Apply merged BeanDefinition post‑processors.

Handle early singleton exposure to resolve circular references.

Populate properties with populateBean(), recursively initializing dependent beans.

Initialize the bean with initializeBean(), which invokes Aware methods, BeanPostProcessor before/after hooks, and any init methods.

Register the bean as disposable with registerDisposableBeanIfNecessary().

After initialization, resolve circular‑reference proxies if needed.

The initializeBean() method (shown below) demonstrates the exact order of callbacks:

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    } else {
        // Aware callbacks (BeanNameAware, BeanClassLoaderAware, BeanFactoryAware)
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // BeanPostProcessor before‑initialization
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // init‑method or InitializingBean.afterPropertiesSet()
        invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        // BeanPostProcessor after‑initialization
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

The destruction path mirrors initialization:

close() → doClose() → destroyBeans() → destroySingletons() → destroySingleton() → destroyBean() → bean.destroy()

. The article notes that the detailed source of the destruction flow is omitted for brevity.

4. Conclusion

Mastering the Spring Bean lifecycle equips developers to leverage the framework’s powerful extension points, avoid common pitfalls such as circular‑reference issues, and implement custom behavior at precise moments during bean creation and teardown.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaIOCSpringBeanPostProcessorSpring FrameworkBean Lifecycle
Shepherd Advanced Notes
Written by

Shepherd Advanced Notes

Dedicated to sharing advanced Java technical insights, daily work snippets, and the power of persistent effort.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.