Inside Spring: How Beans Are Instantiated Step by Step
This article explains the two‑phase lifecycle of Spring beans, covering container startup tasks, metadata loading, bean definition registration, and the detailed instantiation process including object creation strategies, BeanWrapper, property injection, Aware interfaces, post‑processors, and custom init/destroy logic.
For Java developers, Spring has become one of the most popular open‑source frameworks. While we enjoy the benefits of the Spring IoC container, it is essential to understand how the container creates each Bean. This article walks through the Spring Bean instantiation process.
We will not analyze the source code in detail; instead we list the classes Spring uses at each step and describe their responsibilities. For deeper insight, refer to the relevant Spring source files.
Two stages
Spring manages objects called Beans, as evident from XML configuration files. The IoC container works like a production line: beans are the final products, and the container must be started before production begins. Bean lifecycle can be divided into two stages:
Container startup stage
Bean instantiation stage
Container startup stage
1. Configuration metadata
Spring separates object creation from usage. It needs metadata—XML, properties files, annotations, or hard‑coded values—to know how to create objects. This metadata is called configuration metadata.
<bean id="role" class="com.wbg.springxmlbean.entity.Role">
<!-- property elements define class properties
equivalent to:
Role role = new Role();
role.setId(1);
role.setRoleName("高级工程师");
role.setNote("重要人员"); -->
<property name="id" value="1"/>
<property name="roleName" value="高级工程师"/>
<property name="note" value="重要人员"/>
</bean>2. BeanDefinition
All configuration metadata is represented in memory as BeanDefinition objects, similar to how a Person class represents a real person in Java.
3. BeanDefinitionReader
BeanDefinitionReader loads the metadata and converts it into BeanDefinition objects. Different readers handle different formats: XmlBeanDefinitionReader for XML, PropertiesBeanDefinitionReader for properties files, AnnotatedBeanDefinitionReader for annotations, and custom readers can be created for other sources.
4. BeanDefinitionRegistry
After conversion, BeanDefinitions are registered in a BeanDefinitionRegistry, a key‑value store that maps a bean’s id to its BeanDefinition.
5. BeanFactoryPostProcessor
During container startup, BeanFactoryPostProcessor provides an extension point to modify or replace BeanDefinitions before beans are instantiated. For example, placeholder values like ${jdbc.maxIdle} can be resolved to real configuration values.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="maxIdle" value="${jdbc.maxIdle}"/>
<property name="maxActive" value="${jdbc.maxActive}"/>
<property name="maxWait" value="${jdbc.maxWait}"/>
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>After this step, the container startup stage is complete, leaving a registry full of BeanDefinitions ready for instantiation.
Bean instantiation stage
The timing of this stage depends on the developer’s choice of lazy loading. With lazy loading, beans remain as BeanDefinitions until they are requested; otherwise, the container eagerly creates all beans after startup.
1. Object creation strategy
Spring uses the Strategy pattern to create objects, either via reflection or CGLIB bytecode generation, based on configuration.
2. BeanWrapper – the object’s coat
All beans are wrapped in a BeanWrapper, which simplifies reflective operations and provides a uniform way to access bean properties and methods.
3. Setting bean properties
Primitive properties are set directly from metadata or receive default JVM values. Reference properties are injected from already‑created beans; if a dependency is missing, Spring temporarily pauses the current bean’s creation, instantiates the required dependency, and then resumes.
How does Spring resolve circular dependencies? It uses a three‑level cache and can only handle setter‑injection cycles.
4. Aware interfaces
If a bean implements an Aware interface (e.g., ApplicationContextAware), Spring injects the corresponding container object during instantiation.
5. BeanPostProcessor – pre‑processing
BeanFactoryPostProcessor runs in the startup stage, while BeanPostProcessor runs after a bean instance is created, allowing modifications, proxy creation (e.g., for AOP), and other enhancements.
6. Custom initialization logic
Beans can define initialization logic via the InitializingBean interface or an init-method attribute.
7. BeanPostProcessor – post‑processing
After custom init logic, another post‑processor hook allows further extensions.
8. Custom destroy logic
Destruction logic can be provided by implementing DisposableBean or specifying a destroy-method, such as closing a DataSource.
9. Using the bean
Once all steps are complete, the bean can be used like any regular Java object.
10. Destroy callbacks
When the container shuts down, Spring invokes the bean’s destroy callbacks to perform cleanup.
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.
Java Interview Crash Guide
Dedicated to sharing Java interview Q&A; follow and reply "java" to receive a free premium Java interview guide.
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.
