Backend Development 10 min read

Build a Mini Spring IoC Container in 5 Minutes: Hands‑On Tutorial

This article walks through the fundamentals of Spring’s IoC container by manually implementing a lightweight version, covering concepts such as IOC, DI, bean definitions, resource loading, bean registration, and a simple BeanFactory with example code and a test demonstrating singleton caching.

macrozheng
macrozheng
macrozheng
Build a Mini Spring IoC Container in 5 Minutes: Hands‑On Tutorial

Spring is a widely used open‑source framework that has grown into a large ecosystem, making its core concepts hard to grasp at a glance.

This section returns to the essence of Spring and shows how to hand‑craft a minimal Spring container in five minutes.

What Is IOC?

Spring was introduced by Rod Johnson, whose books challenged the traditional Java EE EJB model and led to the creation of the lightweight Spring framework.

Spring’s two core kernels are IOC and AOP, with IOC being the most fundamental.

IOC (Inversion of Control) means the container manages object lifecycles and dependencies, delivering the required objects instead of the code creating them directly.

After introducing IOC, control over object lifecycles shifts from the objects themselves to the container, which is why the term "Inversion of Control" is used.

DI (Dependency Injection) is the concrete way the container supplies required dependencies when instantiating objects, complementing IOC.

Factory and Spring Container

Spring can be viewed as a large factory. To understand its inner workings, we examine a simplified “mini” Spring container.

Produce Products : In Spring, beans are instantiated by the container using reflection.

Inventory Products : Created beans are cached so they are not recreated on every request.

Order Processing : Bean definitions (XML or annotations) act as orders that describe what objects to create and how they depend on each other.

The following sections describe the implementation of this mini container.

Order: Bean Definition

Bean definitions are stored in a simple properties file where each

key

is a bean name and each

value

is the fully‑qualified class name.

<code>userDao:cn.fighter3.bean.UserDao</code>

The corresponding Java class representing a bean definition:

<code>public class BeanDefinition {
    private String beanName;
    private Class beanClass;
    // getters and setters omitted
}</code>

Order Fulfillment: Resource Loader

The resource loader reads the properties file and builds a map of bean names to

BeanDefinition

objects.

<code>public class ResourceLoader {
    public static Map<String, BeanDefinition> getResource() {
        Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>(16);
        Properties properties = new Properties();
        try {
            InputStream inputStream = ResourceLoader.class.getResourceAsStream("/beans.properties");
            properties.load(inputStream);
            for (String key : properties.stringPropertyNames()) {
                String className = properties.getProperty(key);
                BeanDefinition bd = new BeanDefinition();
                bd.setBeanName(key);
                bd.setBeanClass(Class.forName(className));
                beanDefinitionMap.put(key, bd);
            }
            inputStream.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return beanDefinitionMap;
    }
}</code>

Order Allocation: Bean Register

BeanRegister acts as a singleton cache for beans.

<code>public class BeanRegister {
    private Map<String, Object> singletonMap = new HashMap<>(32);
    public Object getSingletonBean(String beanName) {
        return singletonMap.get(beanName);
    }
    public void registerSingletonBean(String beanName, Object bean) {
        if (singletonMap.containsKey(beanName)) return;
        singletonMap.put(beanName, bean);
    }
}</code>

Production Floor: BeanFactory

BeanFactory ties everything together: it loads resources, creates the BeanRegister, and provides

getBean

to retrieve or create beans.

<code>public class BeanFactory {
    private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
    private BeanRegister beanRegister;
    public BeanFactory() {
        beanRegister = new BeanRegister();
        this.beanDefinitionMap = new ResourceLoader().getResource();
    }
    public Object getBean(String beanName) {
        Object bean = beanRegister.getSingletonBean(beanName);
        if (bean != null) return bean;
        return createBean(beanDefinitionMap.get(beanName));
    }
    private Object createBean(BeanDefinition beanDefinition) {
        try {
            Object bean = beanDefinition.getBeanClass().newInstance();
            beanRegister.registerSingletonBean(beanDefinition.getBeanName(), bean);
            return bean;
        } catch (InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }
}</code>

Testing the Mini Container

Example bean class:

<code>public class UserDao {
    public void queryUserInfo() {
        System.out.println("A good man.");
    }
}</code>

JUnit test demonstrating bean retrieval and singleton caching:

<code>public class ApiTest {
    @Test
    public void test_BeanFactory() {
        BeanFactory beanFactory = new BeanFactory();
        UserDao userDao1 = (UserDao) beanFactory.getBean("userDao");
        userDao1.queryUserInfo();
        UserDao userDao2 = (UserDao) beanFactory.getBean("userDao");
        userDao2.queryUserInfo();
    }
}</code>

Running the test prints:

<code>A good man.
A good man.</code>

Thus a functional, though simplified, Spring‑style IoC container is built. Potential improvements include better abstraction, extensibility, and decoupling.

Javabackend developmentIoCSpringdependency injectionBeanFactory
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login 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.