The life cycle of Spring beans

The life cycle of the Bean

1. Initialize the Bean

The container is instantiated by taking information from the BeanDefinition, which is a simple instantiation step without dependency injection.

The instantiated object is wrapped in a BeanWrapper object, which provides an interface to set the properties of the object, avoiding the need for reflection to inject properties.

2. Set object properties (dependency injection)

The instantiated Bean is still in its native state, and Spring then does dependency injection based on the information in BeanDefinition and through the interface provided by BeanWrapper to set properties.

3. Inject Aware interface

Spring detects whether the object implements the xxxAware interface and injects the associated xxxAware instance into the bean.

  • BeanNameAware: To obtain the Bean ID through the reference of the Bean, which is rarely used in general services.
  • BeanFactoryAware: Get Spring BeanFactory containers, such as publish events, etc.
  • ApplicationContextAwaer: Get the Spring ApplicationContext container;

4. BeanPostProcessor preprocessing

If Spring implements the BeanPostProcessor interface, pring will invoke them postProcessBeforeInitialization (Object beans, String beanName) (initialization) method, The purpose is to enhance the Bean instance after it is created successfully, such as modifying the Bean to add a certain function.

5. InitializingBean interface

The InitializingBean interface has only one function: AfterPropertiesSet (), which adds our own custom logic before the bean is formally constructed. Unlike the pre-processing, this function does not have a bean object as it cannot process the bean object itself, only some additional logic can be added.

6. The init method statement

This works as the InitializingBean interface.

7. BeanPostProcessor postprocessing

If Spring implements the BeanPostProcessor interface, pring will invoke them postProcessAfterInitialization (Object beans, String beanName) (initialization) method, effect and 4, Except that 6 is executed before the Bean is initialized, and this is executed after the Bean is initialized, at a different time.

8. The Bean initialization is complete

After the above work, the Bean will reside in the application context for use by the application until the application context is destroyed.

9. DispostbleBean interface

The DispostbleBean interface has only one function: destroy(), which executes the logic in this function before the bean is destroyed.

10. Destroy – method statement

Works with DispostbleBean interface.

code

The Person class implements the interfaces of BeanNameAware, BeanFactoryAware, ApplicationContextAwaer, InitializingBean and DispostbleBean.

package tech.mervyn.demo.entity;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class Person implements BeanNameAware.BeanFactoryAware.ApplicationContextAware.InitializingBean.DisposableBean {

    private String name;

    public Person(a) {
        System.out.println("Call the default constructor to instantiate the object...");
    }

    public void setName(String name) {
        System.out.println("Call Setter method to set property...");
        this.name = name;
    }

    public String getName(a) {
        return name;
    }

    @Override
    public String toString(a) {
        return "Person{" +
                "name='" + name + '\' ' +
                '} ';
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("Get beanName ->" + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Get BeanFactory ->" + beanFactory.hashCode());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Get applicationContext ->" + applicationContext.hashCode());
    }

    @Override
    public void afterPropertiesSet(a) throws Exception {
        System.out.println("Execute InitializingBean logic...");
    }

    public void initMethod(a) {
        System.out.println("Execute init-method declaration logic...");
    }

    @Override
    public void destroy(a) throws Exception {
        System.out.println("Execute DisposableBean logic...");
    }

    public void destroyMethod(a) {
        System.out.println("Execute destroy-method declaration logic..."); }}Copy the code

Custom MyBeanPostProcessor BeanPostProcessor class hierarchy and implement postProcessBeforeInitialization (Object bean, String beanName) and postProcessAfterInitialization (Object beans, String beanName) method.

package tech.mervyn.demo.processor;

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

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor preprocessing," + beanName + "- >" + bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("BeanPostProcessor post-processing," + beanName + "- >" + bean);
        returnbean; }}Copy the code

The configuration class

package tech.mervyn.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tech.mervyn.demo.entity.Person;
import tech.mervyn.demo.processor.MyBeanPostProcessor;

@Configuration
public class AppConfig {

    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public Person person(a) {
        Person person = new Person();
        person.setName("Mervyn");
        return person;
    }

    @Bean
    public MyBeanPostProcessor myBeanPostProcessor(a) {
        return newMyBeanPostProcessor(); }}Copy the code

perform

package tech.mervyn.demo;

import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import tech.mervyn.demo.config.AppConfig;

public class LiftCycleTests {

    @Test
    void liftCycle(a) {
        AnnotationConfigApplicationContext context = newAnnotationConfigApplicationContext(AppConfig.class); context.registerShutdownHook(); }}Copy the code

Output, which removes some useless logs:

22:29:54. 047. [the main] the DEBUG org. Springframework. Beans. Factory. Support. DefaultListableBeanFactory - Creating Shared Instance of singleton bean 'appConfig' 22:29:54.052 [main] INFO org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker - Bean 'appConfig' of type [tech.mervyn.demo.config.AppConfig$$EnhancerBySpringCGLIB$$b60c41a9] is not eligible for getting processed by all BeanPostProcessors (for example: Not eligible for auto-proxying) 22:29:54.072 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'person' calls the default constructor to instantiate the object... Call Setter methods to set properties... Obtain beanName -> Person -> 1390913202 obtain applicationContext -> 1297836716 BeanPostProcessor Person -> person {name='Mervyn'} execute InitializingBean logic... Execute init-method to declare logic... Person -> person {name='Mervyn'} Execute DisposableBean logic... Execute the destroy-method declaration logic...Copy the code

Notice this line in the log: org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker – Bean ‘appConfig’ of type [tech.mervyn.demo.config.AppConfig$$EnhancerBySpringCGLIB$$b60c41a9] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). This is generated when BeanPostProcessor starts up and causes error to dependent beans.