The life cycle of Bean in Spring

Posted by Bea on Tue, 04 Jan 2022 03:09:13 +0100

The life cycle of beans in Spring

1. What is the life cycle of beans in Spring

Spring's biggest feature is Bean oriented (BOP) programming. The Bean managed by spring is a POJO, that is, a simple JavaBean (Bean that does not need to implement any specification). Spring provides many methods to enhance the functions of the managed Bean objects, including the control of the life cycle.

2. Preparation phase before bean creation

Before the Bean is created by Spring, the IoC container will be instantiated first to find the configuration information of all beans managed by Spring. At the same time, beanfactoryprocessor, InstantiationAwareBeanPostProcessor, BeanPostProcessor and other processors will be instantiated.

Interfaceexplain
BeanFactoryPostProcessorThis interface has only one beanfactoryprocessor () method. After BeanFactory is initialized, you can modify the metadata of the Bean. At this time, the Bean has not been instantiated.
InstantiationAwareBeanPostProcessorThe implementation class of the interface will only be instantiated in the preparation stage and will not call any methods.
BeanPostProcessorThe implementation class of the interface will only be instantiated in the preparation stage and will not call any methods.

2.1 code demonstration

package com.wxw.processor.ioc;

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

public class WxwBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public WxwBeanFactoryPostProcessor() {
        System.out.println("Call[ BeanFactoryPostProcessor]Construction method!!!");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        System.out.println("Call[ BeanFactoryPostProcessor]Class postProcessBeanFactory method!!!");
        // Here you can modify the metadata of the Bean
        BeanDefinition userBean = configurableListableBeanFactory.getBeanDefinition("userBean");
        userBean.getPropertyValues().addPropertyValue("age","28");
    }
}
package com.wxw.processor.instantiation;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

public class WxwInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    public WxwInstantiationAwareBeanPostProcessor() {
        System.out.println("Call[ InstantiationAwareBeanPostProcessor]Construction method!!!");
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("Call[ InstantiationAwareBeanPostProcessor]of Before method!!!");
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("Call[ InstantiationAwareBeanPostProcessor]of After method!!!");
        return false;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        return null;
    }
}

package com.wxw.processor.initialize;

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

public class WxwBeanPostProcessor implements BeanPostProcessor {

    public WxwBeanPostProcessor(){
        System.out.println("Call[ BeanPostProcessor]Construction method!!!");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Call[ BeanPostProcessor]Yes[ Before]method!!!");
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Call[ BeanPostProcessor]Yes[ After]method!!!");
        return null;
    }
}

package com.wxw.test;

import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestClass {

    @Test
    public void test1(){
        System.out.println("=====================IoC Container initialization begin=========================");
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        System.out.println("=====================IoC Container initialization end=========================");
    }

}

The operation results are as follows:

=====================IoC Container initialization begin=========================
Call[ BeanFactoryPostProcessor]Construction method!!!
Call[ BeanFactoryPostProcessor]Class postProcessBeanFactory method!!!
Call[ InstantiationAwareBeanPostProcessor]Construction method!!!
Call[ BeanPostProcessor]Construction method!!!
=====================IoC Container initialization end=========================

2.2 sequence diagram

3. Bean instantiation stage

Bean s in Spring will be processed by the relevant methods of the instantiaawarebeanpostprocessor processor in the instantiation phase.

Interfaceexplain
InstantiationAwareBeanPostProcessorThe interface has three methods:
1. postProcessBeforeInstantiation(): this method will be called before Bean is instantiated, if the method returns a non empty object. It will skip the process of Spring creating beans (including dependency injection, initialization, etc.), directly execute the post processor of BeanPostProcessor, and then return this object. If the method returns null, it will execute the normal process of Spring creating beans.

2. postProcessAfterInstantiation(): after the Bean is instantiated, it will be invoked before it is injected. If the method returns to false, it will exit the populateBean() method directly and make the current Bean dependency injection step short. If the method returns true, the normal process will be executed.

3. postProcessProperties(): this method is executed After the After method returns true. You can process the properties of the Bean before Spring sets the property value of the Bean.

3.1 code demonstration

package com.wxw.processor.instantiation;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

import java.lang.reflect.Constructor;

public class WxwInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    public WxwInstantiationAwareBeanPostProcessor() {
        System.out.println("Call[ InstantiationAwareBeanPostProcessor]Construction method!!!");
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("Call[ InstantiationAwareBeanPostProcessor]of Before method!!!");
        Object obj = null;
        try {
            Constructor<?> constructor = beanClass.getConstructor(String.class, Integer.class);
            obj = constructor.newInstance("wxw",20);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("Call[ InstantiationAwareBeanPostProcessor]of After method!!!");
        return false;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        System.out.println("Call[ InstantiationAwareBeanPostProcessor]of postProcessProperties method!!!");
        return pvs;
    }
}
package com.wxw.pojo;

import lombok.Data;
import org.springframework.beans.factory.InitializingBean;

@Data
public class UserBean implements InitializingBean {

    private String name;
    private Integer age;

    public UserBean() {
        System.out.println("Call[ UserBean]Construction method of!!!");
    }

    public UserBean(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        System.out.println("Call[ UserBean]Yes[ setName]method!!!");
        this.name = name;
    }

    public void setAge(Integer age) {
        System.out.println("Call[ UserBean]Yes[ setAge]method!!!");
        this.age = age;
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("[UserBean]Yes[ init]Method execution!!!");
    }
}

The operation results are as follows:

=====================IoC Container initialization begin=========================
Call[ BeanFactoryPostProcessor]Construction method!!!
Call[ BeanFactoryPostProcessor]Class postProcessBeanFactory method!!!
Call[ InstantiationAwareBeanPostProcessor]Construction method!!!
Call[ BeanPostProcessor]Construction method!!!
=====================IoC Container initialization end=========================
Call[ InstantiationAwareBeanPostProcessor]of Before method!!!
Call[ BeanPostProcessor]Yes[ After]method!!!

3.2 sequence diagram

4. Bean initialization phase

In the Bean initialization phase, the related methods of Aware interface implementation class, BeanPostProcessor processing, setBeanFactory method of InitializingBean interface and init method method configured in xml will be executed.

Interfaceexplain
AwareThe class implementing the interface will make the class aware of some properties, such as BeanFactoryAware, BeanNameAware, etc
BeanPostProcessorThe interface has two methods:
1. postProcessBeforeInitialization: executed before the Bean initializes the callback function
2. postProcessAfterInitialization: executed after the Bean initializes the callback function
InitializingBeansetBeanFactory method: initialization callback function of Bean
Init method configuration methodLike the InitializingBean interface method, initialize the callback function

4.1 code demonstration

UserBean class:

package com.wxw.pojo;

import lombok.Data;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;

@Data
public class UserBean implements InitializingBean, BeanFactoryAware {

    private String name;
    private Integer age;

    private BeanFactory beanFactory;

    public UserBean() {
        System.out.println("Call[ UserBean]Construction method of!!!");
    }

    public UserBean(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        System.out.println("Call[ UserBean]Yes[ setName]method!!!");
        this.name = name;
    }

    public void setAge(Integer age) {
        System.out.println("Call[ UserBean]Yes[ setAge]method!!!");
        this.age = age;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Call[ BeanFactoryAware]Yes[ setBeanFactory]method!!!");
        this.beanFactory = beanFactory;
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("[InitializingBean]Yes[ init]Method execution!!!");
    }

    public void init(){
        System.out.println("[init-method]Configured[ init]Method execution!!!");
    }
}

spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userBean" class="com.wxw.pojo.UserBean"
          lazy-init="true"
          init-method="init"
          scope="singleton">
        <property name="name" value="Wxw"/>
        <property name="age" value="18"/>
    </bean>

    <bean id="wxwBeanFactoryPostProcessor" class="com.wxw.processor.ioc.WxwBeanFactoryPostProcessor"></bean>

    <bean id="wxwInstantiationAwareBeanPostProcessor" class="com.wxw.processor.instantiation.WxwInstantiationAwareBeanPostProcessor"></bean>

    <bean id="wxwBeanPostProcessor" class="com.wxw.processor.initialize.WxwBeanPostProcessor"></bean>

</beans>

BeanPostProcessor implementation class:

package com.wxw.processor.initialize;

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

public class WxwBeanPostProcessor implements BeanPostProcessor {

    public WxwBeanPostProcessor(){
        System.out.println("Call[ BeanPostProcessor]Construction method!!!");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Call[ BeanPostProcessor]Yes[ Before]method!!!");
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Call[ BeanPostProcessor]Yes[ After]method!!!");
        return bean;
    }
}

Test class:

package com.wxw.test;

import com.wxw.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestClass {

    @Test
    public void test1(){
        System.out.println("=====================IoC Container initialization begin=========================");
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        System.out.println("=====================IoC Container initialization end=========================");
        UserBean userBean = (UserBean) applicationContext.getBean("userBean");
        System.out.println(userBean);
    }

}

Operation results:

=====================IoC Container initialization begin=========================
Call[ BeanFactoryPostProcessor]Construction method!!!
Call[ BeanFactoryPostProcessor]Class postProcessBeanFactory method!!!
Call[ InstantiationAwareBeanPostProcessor]Construction method!!!
Call[ BeanPostProcessor]Construction method!!!
=====================IoC Container initialization end=========================
Call[ InstantiationAwareBeanPostProcessor]of Before method!!!
Call[ UserBean]Construction method of!!!
Call[ InstantiationAwareBeanPostProcessor]of After method!!!
Call[ InstantiationAwareBeanPostProcessor]of postProcessProperties method!!!
Call[ UserBean]Yes[ setName]method!!!
Call[ UserBean]Yes[ setAge]method!!!
Call[ BeanFactoryAware]Yes[ setBeanFactory]method!!!
Call[ BeanPostProcessor]Yes[ Before]method!!!
[InitializingBean]Yes[ init]Method execution!!!
[init-method]Configured[ init]Method execution!!!
Call[ BeanPostProcessor]Yes[ After]method!!!
UserBean{name='Wxw', age=28}

4.2 sequence diagram

5. Bean destruction phase

When the Bean is destroyed, the destroy method of DisposableBean interface and the destroy method configured in xml will be executed.

5.1 code demonstration

UserBean class:

package com.wxw.pojo;

import lombok.Data;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

@Data
public class UserBean implements InitializingBean, BeanFactoryAware, ApplicationContextAware, DisposableBean {

    private String name;
    private Integer age;

    private BeanFactory beanFactory;
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Call[ ApplicationContextAware]Yes[ setApplicationContext]method!!!");
        this.applicationContext = applicationContext;
    }

    public UserBean() {
        System.out.println("Call[ UserBean]Construction method of!!!");
    }

    public UserBean(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public void setName(String name) {
        System.out.println("Call[ UserBean]Yes[ setName]method!!!");
        this.name = name;
    }

    public void setAge(Integer age) {
        System.out.println("Call[ UserBean]Yes[ setAge]method!!!");
        this.age = age;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Call[ BeanFactoryAware]Yes[ setBeanFactory]method!!!");
        this.beanFactory = beanFactory;
    }

    @Override
    public String toString() {
        return "UserBean{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("[InitializingBean]Yes[ init]Method execution!!!");
    }

    public void init(){
        System.out.println("[init-method]Configured[ init]Method execution!!!");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("[DisposableBean]Yes[ destroy]Method execution");
    }

    public void beanDestroy(){
        System.out.println("[destroy-method]Configured[ beanDestroy]Method execution!!!");
    }
}

spring-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userBean" class="com.wxw.pojo.UserBean"
          lazy-init="true"
          init-method="init"
          destroy-method="beanDestroy"
          scope="singleton">
        <property name="name" value="Wxw"/>
        <property name="age" value="18"/>
    </bean>

    <bean id="wxwBeanFactoryPostProcessor" class="com.wxw.processor.ioc.WxwBeanFactoryPostProcessor"></bean>

    <bean id="wxwInstantiationAwareBeanPostProcessor" class="com.wxw.processor.instantiation.WxwInstantiationAwareBeanPostProcessor"></bean>

    <bean id="wxwBeanPostProcessor" class="com.wxw.processor.initialize.WxwBeanPostProcessor"></bean>

</beans>

Test class:

package com.wxw.test;

import com.wxw.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestClass {

    @Test
    public void test1(){
        System.out.println("=====================IoC Container initialization begin=========================");
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
        System.out.println("=====================IoC Container initialization end=========================");
        UserBean userBean = (UserBean) applicationContext.getBean("userBean");
        System.out.println(userBean);
        System.out.println("=====================IoC Container destruction begin=========================");
        applicationContext.close();
        System.out.println("=====================IoC Container destruction end=========================");
    }

}

Execution results:

=====================IoC Container initialization begin=========================
Call[ BeanFactoryPostProcessor]Construction method!!!
Call[ BeanFactoryPostProcessor]Class postProcessBeanFactory method!!!
Call[ InstantiationAwareBeanPostProcessor]Construction method!!!
Call[ BeanPostProcessor]Construction method!!!
=====================IoC Container initialization end=========================
Call[ InstantiationAwareBeanPostProcessor]of Before method!!!
Call[ UserBean]Construction method of!!!
Call[ InstantiationAwareBeanPostProcessor]of After method!!!
Call[ InstantiationAwareBeanPostProcessor]of postProcessProperties method!!!
Call[ UserBean]Yes[ setName]method!!!
Call[ UserBean]Yes[ setAge]method!!!
Call[ BeanFactoryAware]Yes[ setBeanFactory]method!!!
Call[ ApplicationContextAware]Yes[ setApplicationContext]method!!!
Call[ BeanPostProcessor]Yes[ Before]method!!!
[InitializingBean]Yes[ init]Method execution!!!
[init-method]Configured[ init]Method execution!!!
Call[ BeanPostProcessor]Yes[ After]method!!!
UserBean{name='Wxw', age=28}
=====================IoC Container destruction begin=========================
[DisposableBean]Yes[ destroy]Method execution
[destroy-method]Configured[ beanDestroy]Method execution!!!
=====================IoC Container destruction end=========================

The process has ended with exit code 0

Topics: Java Spring Spring Boot