Deep Dive into Spring IOC Container Initialization Process

This article provides a comprehensive, step‑by‑step analysis of how Spring's IoC container is initialized, covering resource loading, BeanDefinition creation, BeanFactory setup, template‑method refresh logic, and practical debugging tips, all illustrated with UML diagrams and code snippets.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Deep Dive into Spring IOC Container Initialization Process

As a frequent Spring backend developer, the author decided to explore the inner workings of the Spring IoC container, starting from the single line of code that creates a ClassPathXmlApplicationContext and expanding into a detailed walkthrough of the entire initialization sequence.

Reading Tips

Source code analysis can be tedious, but it offers deep insight.

The article is long and heavily illustrated.

Familiarity with design patterns and the six SOLID principles is recommended.

The author is a senior undergraduate eager for feedback.

Readers are encouraged to debug in an IDE while following the article.

UML diagrams are generated in IDEA using Ctrl+Shift+Alt+U, then Ctrl+Alt+B, then Enter.

The first step is to understand the resource file applicationContext.xml, which contains bean definitions. Spring abstracts all resources via the Resource interface, applying the Strategy pattern to handle xml, properties, txt, etc. The ResourceLoader component loads these resources, with implementations such as FileSystemResourceLoader and ServletContextResourceLoader. The ApplicationContext itself implements ResourceLoader, enabling calls like new ClassPathXmlApplicationContext("applicationContext.xml") to obtain the XML file.

Bean definitions are represented by the BeanDefinition hierarchy. The <bean/> element in XML maps to a BeanDefinition object, with concrete classes like RootBeanDefinition, GenericBeanDefinition, and ChildBeanDefinition. These definitions are stored in a BeanDefinitionRegistry, essentially an in‑memory map of bean metadata.

To convert resources into BeanDefinition objects, Spring uses a BeanDefinitionReader abstraction. Implementations such as XmlBeanDefinitionReader and PropertiesBeanDefinitionReader parse the respective resource types and register the resulting definitions with the registry.

During the refresh phase, the refresh() template method orchestrates the whole process:

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        prepareBeanFactory(beanFactory);
        try {
            postProcessBeanFactory(beanFactory);
            invokeBeanFactoryPostProcessors(beanFactory);
            registerBeanPostProcessors(beanFactory);
            initMessageSource();
            initApplicationEventMulticaster();
            onRefresh();
            registerListeners();
            finishBeanFactoryInitialization(beanFactory);
            finishRefresh();
        } catch (BeansException ex) {
            destroyBeans();
            cancelRefresh(ex);
            throw ex;
        } finally {
            resetCommonCaches();
        }
    }
}

The prepareRefresh() method sets the startup timestamp, activates the context, and validates required properties. obtainFreshBeanFactory() creates a new DefaultListableBeanFactory, loads bean definitions via an XmlBeanDefinitionReader, and registers them. refreshBeanFactory() ensures any existing factory is destroyed before a fresh one is built.

Key code snippets illustrate these steps, for example the method that resolves configuration paths:

protected String resolvePath(String path) {
    return getEnvironment().resolveRequiredPlaceholders(path);
}

and the environment creation:

public ConfigurableEnvironment getEnvironment() {
    if (this.environment == null) {
        this.environment = createEnvironment();
    }
    return this.environment;
}

A practical example shows a simple Student class and its bean declarations in XML, demonstrating how the container instantiates and wires objects:

package com.wokao666;
public class Student {
    private int id;
    private String name;
    private int age;
    // getters, setters, constructors, toString() ...
}
<bean id="stu1" class="com.wokao666.Student">
    <property name="id" value="1"/>
    <property name="name" value="Alice"/>
    <property name="age" value="20"/>
</bean>

The article concludes by summarizing the two main outcomes of the first ten steps: (1) the ClassPathXmlApplicationContext instance is created and its resourcePatternResolver is ready to turn XML files into Resource objects, and (2) the bean factory is populated with BeanDefinition objects ready for instantiation.

Readers are invited to comment on any inaccuracies and to share their own observations, emphasizing the value of documenting knowledge for future reference.

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.

BackendDesign PatternsJavaIoCspringdependency-injection
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

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.