IoC Container System

The IoC container is the core module of Spring and is a framework solution that abstracts object management and dependency relationship management. Spring provides many containers, among which BeanFactory is the top-level container (root container) and cannot be instantiated. It defines the principles that all IoC containers must follow.

BeanFactory is the top-level container (root container) and cannot be instantiated. It defines the principles that all IoC containers must follow.

ApplicationContext inherits from BeanFactory’s sub-interface and also inherits interfaces like ResourcesLoader and MessageSource, so it provides richer functionality.


What is IoC (Inversion of Control)?

IoC (Inversion of Control) is a design principle referring to transferring control of objects from the program to an external container or framework.

IoC transforms hard-coded dependency relationships into dynamic injection, thereby enhancing system scalability, maintainability, and decoupling.

In IoC, the core idea is: the system no longer explicitly creates objects through the application, but instead creates and manages objects through the container. The container is responsible for controlling object lifecycle and providing dependencies when needed.


IoC Container Functions

The main functions of the IoC container are:

  • Object Creation: The container is responsible for instantiating objects without explicit code
  • Dependency Injection: The container automatically injects a object’s dependencies into that object
  • Lifecycle Management: The container controls object creation, destruction, and management
  • Decoupling: Dependency relationships between objects are managed through the container

IoC Container Working Principle

The IoC container mainly relies on the Dependency Injection (DI) mechanism to achieve inversion of control. There are three common ways for dependency injection:

  1. Constructor Injection: Passes dependent objects to the target object through the constructor
  2. Setter Injection: Injects dependencies into the target object by providing setter methods
  3. Interface Injection: The target object implements an interface, and the container provides dependencies through that interface

IoC Container Core Functions

  • Object registration: The container registers different types of objects through configuration files or code
  • Dependency injection: The container automatically injects other objects that an object depends on through configuration or annotations
  • Lifecycle management: The container controls object lifecycle, such as singleton mode, prototype mode, etc.
  • Scope management: The container supports objects of different scopes
  • Event management: The container supports event-driven mechanisms

IoC Container Advantages

  • Decoupling: Through IoC containers, components in the system no longer directly depend on each other
  • Scalability: Dependency relationships are dynamically managed by the container
  • Maintainability: IoC containers manage object lifecycle and dependency relationships
  • Modularity: Managing objects through containers enhances isolation between different modules
  • Test-friendly: IoC containers make unit testing easier

Bean Lifecycle

Write Code

WzkBean

package wzk.bean;

import org.springframework.beans.factory.InitializingBean;

public class WzkBean implements InitializingBean {

    public WzkBean() {
        System.out.println("WzkBean constructor");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("WzkBean afterPropertiesSet");
    }
}

WzkBeanPostProcessor

package wzk.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class WzkBeanPostProcessor implements BeanPostProcessor {

    public WzkBeanPostProcessor() {
        System.out.println("WzkBeanPostProcessor constructor");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("WzkBeanPostProcessor postProcessBeforeInitialization");
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("WzkBeanPostProcessor postProcessAfterInitialization");
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

WzkBeanFactoryPostProcessor

package wzk.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class WzkBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public WzkBeanFactoryPostProcessor() {
        System.out.println("WzkBeanFactoryPostProcessor constructor");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("WzkBeanFactoryPostProcessor postProcessBeanFactory");
    }
}

Configure applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd
">
    <bean id="wzkBean" class="wzk.bean.WzkBean"></bean>
    <bean id="wzkBeanPostProcessor" class="wzk.bean.WzkBeanPostProcessor"></bean>
    <bean id="wzkBeanFactoryPostProcessor" class="wzk.bean.WzkBeanFactoryPostProcessor"></bean>
</beans>

Test Code

public class WzkIocTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        WzkBean wzkBean = (WzkBean) context.getBean("wzkBean");
        System.out.println(wzkBean);
    }
}

Run Result

WzkBeanFactoryPostProcessor constructor
WzkBeanFactoryPostProcessor postProcessBeanFactory
WzkBeanPostProcessor constructor
WzkBean constructor
WzkBeanPostProcessor postProcessBeforeInitialization
WzkBean afterPropertiesSet
WzkBeanPostProcessor postProcessAfterInitialization
wzk.bean.WzkBean@40005471