Start writing the spring ioc framework from scratch and learn more about spring source code

Keywords: Java Spring JSON xml


Ioc Is a simplified implementation version of the spring ioc core functionality for easy learning and understanding of principles.

Purpose of Creation

Spring has been used for a long time, very frequently for spring, and in fact has never been quiet about learning the source code.

However, one problem with the spring source is that it is too abstract, which increases the cost of learning.

So this project has evolved from a deep-rooted one, which only implements the core functions of spring and makes it easy for you and others to learn the core principles of spring.

Core of spring

The core of Spring is spring-beans, on which all the following spring-boot s, spring-cloud s, are built.

When someone asks you about spring, I hope you can talk about your own deeper insights into Sprioc, rather than just a few sentences from people online.

What is IOC

Inversion of Control (IoC) is a design principle in object-oriented programming that can be used to reduce the coupling between computer code.

The most common way is called Dependency Injection (DI).

By controlling inversion, when an object is created, a reference to the object on which it depends is passed to it by an external entity that controls all objects in the system.

Alternatively, dependencies are injected into the object.

Why IOC is needed

IoC is a decoupling method.

We know that Java is an object-oriented language. Everything is Object in Java. Our program consists of several objects.

As our projects grow and co-developers grow, our classes grow and references between classes grow exponentially.

Such a project would be a disaster if we introduced the Ioc framework.

A framework maintains the lifecycle of a class and references between classes.

Our system will become like this:

At this point we found that the IoC framework maintains the relationship between our classes and injects them into the required classes.

That is, the user of the class is only responsible for use, not maintenance.

Delegate professional work to a professional framework to complete, greatly reducing the complexity of development.

Quick Start

Introduction of maven


Test preparation

All test code, see the test module.

public class Apple {

    public void color() {
        System.out.println("Apple color: red. ");

  • apple.json

Similar to the xml configuration, we temporarily use json for configuration validation.


Execute Tests

  • test
BeanFactory beanFactory = new JsonApplicationContext("apple.json");
Apple apple = (Apple) beanFactory.getBean("apple");
  • Journal
Apple color: red.

spring Basic Implementation Process


spring-beans is all about beans.

BeanFactory is responsible for managing the life cycle of bean s. This section shows the simple implementation process of the first section.

spring Core Process

Spring IoC consists mainly of the following steps.

  1. Initialize the IoC container.

  2. Read the configuration file.

  3. Converts a configuration file to a data structure for container identification pairs (this data structure is called BeanDefinition in Spring)

  4. Instantiate corresponding objects in turn using data structures

  5. Dependencies between injection objects

Abstraction of BeanDefinition

BeanDefinition is spring's abstraction of java bean properties, through which a configuration file can be either xml/json/properties/yaml or even an annotation sweep package.

This provides great flexibility for the expansion of spring.

Considering the simplicity of implementation, this framework initially implements only json and annotation-based sweep packages.

Later, if you have time to consider adding an implementation of xml, it is actually more XML parsing workload, the core process has been fully implemented.

Implement Source Selection

BeanDefinition correlation

Contains the basic information abstraction for Java beans.


Its default implementation is, which is the most basic java POJO to implement an interface

See DefaultBeanDefinition

 * Object Definition Properties
 * @author binbin.hou
 * @since 0.0.1
public interface BeanDefinition {

     * Name
     * @return Name
     * @since 0.0.1
    String getName();

     * Set Name
     * @param name Name
     * @since 0.0.1
    void setName(final String name);

     * Class Name
     * @return Class Name
    String getClassName();

     * Set Class Name
     * @param className Class Name
     * @since 0.0.1
    void setClassName(final String className);


BeanFactory Core Management Related

 * bean Factory Interface
 * @author binbin.hou
 * @since 0.0.1
public interface BeanFactory {

     * Get the corresponding instance information by name
     * @param beanName bean Name
     * @return Object Information
     * @since 0.0.1
    Object getBean(final String beanName);

     * Gets the implementation of the specified type
     * @param beanName Property Name
     * @param tClass type
     * @param <T> generic paradigm
     * @return Result
     * @since 0.0.1
    <T> T getBean(final String beanName, final Class<T> tClass);


For the most basic implementation of the interface, the source code is as follows:

 * bean Factory Interface
 * @author binbin.hou
 * @since 0.0.1
public class DefaultBeanFactory implements BeanFactory {

     * Object Information map
     * @since 0.0.1
    private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();

     * Object map
     * @since 0.0.1
    private Map<String, Object> beanMap = new ConcurrentHashMap<>();

     * Registered Object Definition Information
     * @since 0.0.1
    protected void registerBeanDefinition(final String beanName, final BeanDefinition beanDefinition) {
        // You can add listeners here
        this.beanDefinitionMap.put(beanName, beanDefinition);

    public Object getBean(String beanName) {
        Object bean = beanMap.get(beanName);
        if(ObjectUtil.isNotNull(bean)) {
            // This returns a singleton directly, and if the user specifies multiple instances, a new one will be created each time.
            return bean;

        // Get corresponding configuration information
        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if(ObjectUtil.isNull(beanDefinition)) {
            throw new IocRuntimeException(beanName + " not exists in bean define.");

        // Direct basis
        Object newBean = createBean(beanDefinition);
        // Here you can add the corresponding listener
        beanMap.put(beanName, newBean);
        return newBean;

     * Creating objects from object definition information
     * @param beanDefinition Object Definition Information
     * @return Created object information
     * @since 0.0.1
    private Object createBean(final BeanDefinition beanDefinition) {
        String className = beanDefinition.getClassName();
        Class clazz = ClassUtils.getClass(className);
        return ClassUtils.newInstance(clazz);

    public <T> T getBean(String beanName, Class<T> tClass) {
        Object object = getBean(beanName);
        return (T)object;


ClassUtils is a class-based reflection tool class, as detailed in


The basic implementation based on the json profile implementation is shown in the sample code for the start type.

 * JSON Application Context
 * @author binbin.hou
 * @since 0.0.1
public class JsonApplicationContext extends DefaultBeanFactory {

     * File Name
     * @since 0.0.1
    private final String fileName;

    public JsonApplicationContext(String fileName) {
        this.fileName = fileName;

        // Initialize Configuration

     * Initialization configuration related information
     * <pre>
     *  new TypeReference<List<BeanDefinition>>(){}
     * </pre>
     * Read the file:
     * @since 0.0.1
    private void init() {
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName);
        final String jsonConfig = FileUtil.getFileContent(is);
        List<DefaultBeanDefinition> beanDefinitions = JsonBs.deserializeArray(jsonConfig, DefaultBeanDefinition.class);
        if(CollectionUtil.isNotEmpty(beanDefinitions)) {
            for (BeanDefinition beanDefinition : beanDefinitions) {
                super.registerBeanDefinition(beanDefinition.getName(), beanDefinition);



At this point, a basic spring ioc is basically implemented.

If you want to continue learning, you can refer to the following code branches separately.

Branch description

Basic implementation of v0.0.1-BeanFactory

Basic implementation of v0.0.2-ListBeanFactory

v0.0.3 - Singleton and Delayed Loading

v0.0.4 - Initialization and destruction methods

v0.0.5-RespCode Add and Code Optimization

v0.0.6-Constructor and factoryMethod New Object

v0.0.7-property property settings

v0.0.8-Aware listener and PostProcessor

v0.0.9-Parent attribute inheritance

v0.1.0 - Cyclic Dependency Detection

v0.1.1-@Configuration-java code configuration

v0.1.2-@Bean-java object definition

v0.1.3-@Lazy-@Scope-java object property configuration

v0.1.4-@Import Configuration Import

v0.1.5-@Bean parameter construction and @Description

v0.1.6-@Autowired Auto-assembly Annotation Support

v0.1.7-@Primary Specify Priority Note

v0.1.8-@Conditional Conditional Annotation Support

v0.1.9-Environment and @Profile implementation

v0.1.10-Property profile related and @Value/@PropertyResource implementation

v0.1.11-@ComponentScan package scanning support

Expand reading

What is Java IOC-00-ioc

Posted by Orpheus13 on Mon, 02 Dec 2019 16:07:13 -0800