Understanding the Spring Bean Instantiation Process
This article explains how the Spring IoC container prepares and creates Bean instances, detailing the two main phases—container startup and Bean instantiation—along with the roles of BeanDefinition, BeanFactoryPostProcessor, BeanWrapper, Aware interfaces, BeanPostProcessor, and custom initialization and destruction logic.
For Java developers, Spring is one of the most popular open‑source frameworks, and beyond enjoying the benefits of the Spring IoC container, it is essential to understand how Spring creates each Bean. This article outlines the Bean instantiation process without diving into source code, focusing on the classes involved and their responsibilities.
Two Phases
Spring manages objects called Beans. The Bean lifecycle can be divided into two phases: the container startup phase and the Bean instantiation phase.
Container Startup Phase
1. Configuration Metadata
Spring needs metadata (XML, properties, annotations, or hard‑coded values) that describe how to create objects. This metadata is called configuration metadata.
<bean id="role" class="com.wbg.springxmlbean.entity.Role">
<!-- property elements define class attributes
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.
3. BeanDefinitionReader
Different readers (e.g., XmlBeanDefinitionReader, PropertiesBeanDefinitionReader, AnnotatedBeanDefinitionReader) load metadata and convert it into BeanDefinition instances.
4. BeanDefinitionRegistry
The loaded BeanDefinitions are stored in a registry (a key‑value map) that allows the container to locate a definition by its id.
5. BeanFactoryPostProcessor
During startup, BeanFactoryPostProcessor can modify or replace BeanDefinitions, for example to resolve placeholder values such as ${jdbc.url} in the following configuration:
<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="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>After this phase, the container has a fully prepared set of BeanDefinitions ready for instantiation.
Bean Instantiation Phase
The timing of this phase depends on the chosen loading strategy (eager or lazy). If lazy loading is enabled, Beans remain as definitions until they are requested; otherwise, the container instantiates all Beans immediately after startup.
1. Object Creation Strategy
Spring uses the Strategy pattern to create objects, either via reflection or CGLIB bytecode generation, configurable by the developer.
2. BeanWrapper – The Object’s Wrapper
Every created Bean is wrapped by a BeanWrapper, which simplifies reflective operations such as property access and method invocation.
3. Setting Object Properties
Primitive properties are set directly from metadata; reference properties are injected from already‑created Beans. If a dependency is not yet available, Spring temporarily pauses the current Bean’s creation and resolves the dependency first.
How does Spring solve circular dependencies? It uses a three‑level cache and can only resolve setter‑injection cycles.
4. Aware Interface Checks
If a Bean implements an Aware interface (e.g., ApplicationContextAware), Spring injects the corresponding container object during this step.
5. BeanPostProcessor – Pre‑Initialization
BeanPostProcessor runs before a Bean is placed into the container, allowing modification or replacement of the Bean instance. This is also where AOP proxies are created.
6. Custom Initialization Logic
Developers can define initialization logic via the InitializingBean interface or an init-method attribute.
7. BeanPostProcessor – Post‑Initialization
After custom init logic, BeanPostProcessor can perform additional processing.
8. Custom Destruction Logic
Destruction logic can be provided by implementing DisposableBean or specifying a destroy-method (e.g., closing a DataSource).
9. Usage
Once all steps are complete, the Bean is ready for normal use just like any regular Java object.
10. Destruction Callback
When the container shuts down, Spring invokes the configured destroy callbacks, completing the Bean’s lifecycle.
The bridge between the startup and instantiation phases is the bean’s lazy‑loading strategy; enabling it delays instantiation until the Bean is actually needed.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
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.