Demystifying Spring Bean Creation: From Simple Instantiation to Three‑Level Caching
This article breaks down Spring's bean lifecycle, explaining the minimal creation steps, the role of BeanFactoryPostProcessor and BeanPostProcessor, how Spring resolves bean references, handles circular dependencies with three‑level caches, and clarifies common misconceptions about proxy generation.
1. Introduction
Spring is a core framework for Java backend development, and understanding its bean creation process is essential not only for interviews but also for real‑world projects. The article starts by listing three typical interview questions: when proxy objects are generated, how circular dependencies are solved, and what the three‑level cache means.
2. Minimal Bean Creation Flow
Obtain Bean Definition – Scan the classpath, collect metadata (type, name, constructor, properties) and store it in a map.
Instantiate Bean – Use the no‑arg constructor from the definition to create a raw object, similar to new.
Populate Properties – Fill the newly created instance with property values from the definition.
Initialize Bean – If the bean implements InitializingBean, invoke afterPropertiesSet() (or a custom init‑method).
These four steps constitute the core lifecycle. Spring also provides extension points before and after steps 2‑4 via BeanPostProcessor and BeanFactoryPostProcessor.
3. Post‑Processors
Spring defines two main categories of post‑processors: BeanFactoryPostProcessor (including BeanDefinitionRegistryPostProcessor) – operates on bean definitions before any bean is instantiated. BeanPostProcessor – operates on actual bean instances during creation, allowing custom modification.
Examples include MyBatis’s MapperFactoryBean registration and user‑defined processors that modify bean properties or wrap beans with proxies.
BeanFactoryPostProcessor Example
MyBatis scans @Mapper interfaces, creates a MapperFactoryBean definition, and registers it in the bean definition registry.
BeanPostProcessor Example
Custom BeanPostProcessor implementations can intercept bean creation to add behavior such as logging, security checks, or proxy wrapping.
4. Reference Handling and Caching
When a bean references another bean, Spring must manage three scenarios:
Reference to an existing bean – Retrieved directly from the first‑level cache (fully initialized beans).
Reference to a bean not yet created – Spring creates the missing bean on demand; the partially created bean is stored in the third‑level cache (early bean references).
Circular dependencies – Detected via the SingletonCurrentlyInCreation set; Spring resolves them by exposing an early reference from the third‑level cache and later moving the bean to the second‑level cache.
The three caches correspond to different bean states: first‑level holds fully initialized beans, second‑level holds early references (often proxies), and third‑level holds bean instances that have been instantiated but not yet populated.
Circular Dependency Resolution
When Bean A depends on Bean B and vice versa, Spring creates A, stores it in the third‑level cache, then creates B. Upon detecting that A is already in creation, Spring retrieves A’s early reference from the third‑level cache, possibly wraps it with a proxy (via wrapIfNecessary), and injects it into B. After B is fully initialized, A is completed and moved to the first‑level cache.
Proxy Generation in Circular Dependencies
Proxy creation does not change the underlying object identity; the proxy and the target share the same memory address, ensuring that circular references remain consistent regardless of whether a proxy is involved.
5. Deep Dive into the Three‑Level Cache
Although the term “three‑level cache” resembles CPU cache hierarchies, in Spring it is a logical separation rather than a performance optimization. The caches store beans at different lifecycle stages, not for speed but for clarity and correct dependency resolution.
Key points:
The third‑level cache is essential for breaking circular dependencies.
Even without AOP proxies, the three‑level cache is still used.
Spring could technically store all beans in a single collection, but the layered approach makes the process easier to understand and maintain.
6. Detailed Bean Creation Process (Spring 4)
The article concludes with a comprehensive diagram (omitted here) that maps every step of Spring 4’s bean creation, from definition loading to final registration in the singleton cache. Readers are encouraged to refer to the source code for exact method calls such as createBean, populateBean, initializeBean, and wrapIfNecessary.
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.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
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.
