Download the source code

This chapter source github

What is the Spring Bean lifecycle

For normal Java objects, the object is created when new, and then the object can be used. Once the object is no longer in use, It is automatically garbage collected by Java.

The objects in Spring are beans. Beans are not much different from normal Java objects, except that Spring no longer uses the new object itself. Instead, the IoC container helps us instantiate and manage the object. IoC is all about coupling between objects, and the lifecycle of Spring beans is completely controlled by the container.

The life cycle of the Bean

The lifecycle stages of a Spring bean are:

Graph LR Bean definition --> Bean Registration Bean registration --> Actualize --> Dependency Injection --> Initialize --> Destroy
  • 1.Bean definitionLoad the meta information of the read bean from an XML or annotation locator resource and define it as a BeanDefinition object
  • 2.Bean registered: Puts the BeanDefinition object into the cache pool map according to the appropriate rules
  • 3.instantiationInstantiate the real bean from the BeanDefinition, that is, call the constructor
  • 4.Dependency injectionProperty assignment calls setter methods, which are called DI
  • 5.Initialize theInitialization is the phase in which users can customize extensions
  • 6.The destructionDestruction is the phase where users can customize extensions

Note: The others are extension points before and after this stage

The Spring perspective looks at the definition and registration of beans

refresh()

public void refresh(a) throws BeansException, IllegalStateException {
    synchronized(this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
         // The preparation Bean initializes the relevant environment information, providing an empty implementation of the initPropertySources() method inside to provide the user with an opportunity to change the relevant environment information
        this.prepareRefresh();
        // Create an instance of BeanFactory and register the related bean information
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        // Register Aware and Processor instances, and register some Editor information for subsequent processing requests
        this.prepareBeanFactory(beanFactory);

        try {
            // provides an empty method for subclasses to customize some information about the generated BeanFactory
            this.postProcessBeanFactory(beanFactory);
            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // Call the methods associated with BeanFactoryPostProcessor and its subinterfaces, which provide an entry to the caller to modify the generated BeanDefinition
            this.invokeBeanFactoryPostProcessors(beanFactory);
            // Register BeanPostProcessor
            this.registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();
            // Initialize the bean information required for internationalization
            this.initMessageSource();
            // Initializes the bean information for the event broadcaster
            this.initApplicationEventMulticaster();
            // provides an empty method that subclasses can use to provide custom bean information or to modify existing bean information
            this.onRefresh();
            // Register event listeners
            this.registerListeners();
             // Instantiation of registered non-deferred (configuration file specified) beans
            this.finishBeanFactoryInitialization(beanFactory);
            // Clear the cached resource information, initialize some beans that declare period-dependent, and publish events that the Context has been initialized
            this.finishRefresh();
        } catch (BeansException var10) {
            if (this.logger.isWarnEnabled()) {
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var10);
            }
             // If an exception occurs, the generated bean is destroyed
            this.destroyBeans();
            // Reset the refresh field information
            this.cancelRefresh(var10);
            throw var10;
        } finally {
            // Initialize some cache information
            this.resetCommonCaches(); contextRefresh.end(); }}}Copy the code

View the bean definition and registration from the SpringBoot perspective

1. Automatically load configuration classes

2. Bean definition and registration

Note: SpringBoot just has more automatic configuration processes than Spring, with a layer of logic wrapped around spring.

Instantiation, dependency injection, initialization

AbstractAutowireCapableBeanFactory AutowireCapableBeanFactory interface for an implementation class, A method of AbstractAutowireCapableBeanFactory implementation class doCreateBean ()

/ / position: AbstractAutowireCapableBeanFactory# doCreateBean
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
    }

    if (instanceWrapper == null) {
    	// Instantiation phase
        instanceWrapper = this.createBeanInstance(beanName, mbd, args); }... Object exposedObject = bean;try {
    	// Dependency injection, attribute assignment phase
        this.populateBean(beanName, mbd, instanceWrapper);
        // Initialization phase
        exposedObject = this.initializeBean(beanName, exposedObject, mbd);
    } catch(Throwable var18) { ... }... }Copy the code

As you can see, three methods are called separately:

  1. CreateBeanInstance () -> instantiate
  2. PopulateBean () -> Dependency injection
  3. InitializeBean () -> initialize

The destruction

The destruction stage is invoked, the container closed in ConfigurableApplicationContext# close ()

As for the xxxAware, BeanPostProcessor, BeanFactoryPostProcessor classes, they are just a series of extension points to the main process.

The extension point of the Bean’s life cycle

There are many extension points in the life cycle of Spring beans, and it is not possible to list them all here, just the core extension points. That’s why Spring is so extensible, opening up as many doors as possible to make a feature as cohesive and loosely coupled as possible, so that users can use whatever they want, rather than just one big, all-in-one thing.

The Bean level

The implementation classes for these interfaces are bean-based, and only the beans that implement these interfaces are relevant.

  • BeanNameAware
  • BeanFactoryAware
  • ApplicationContextAware
  • InitializingBean
  • DisposableBean

Also a lot of xxxAware, these are not used, the following life cycle tests do not add, such as:

  • BeanClassLoaderAware
  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ServletContextAware

Container level

The implementation classes for these interfaces are bean-independent and registered with the Spring container. Their implementation classes are commonly referred to as the post-processor.

These post-handlers come into play whenever the Spring container creates any beans

  • BeanPostProcessor
  • InstantiationAwareBeanPostProcessor (InstantiationAwareBeanPostProcessor inherited BeanPostProcessor)
  • The factory post-processor interface is also container-level. Called immediately after the application context assembs the configuration file:
    • AspectJWeavingEnabler
    • ConfigurationClassPostProcessor
    • CustomAutowireConfigurer

Common interface

InstantiationAwareBeanPostProcessor

  • This class is a subinterface of BeanPostProcessor. The following methods are commonly used:
    • PostProcessBeforeInstantiation (Class beanClass, String beanName) : call before bean instantiation
    • PostProcessProperties (PropertyValues PVS, Object Bean, String beanName) : Called after the bean is instantiated but before the properties are set
    • PostProcessAfterInstantiation (Class beanClass, String beanName) : call after bean instantiation

BeanNameAware

  • The BeanNameAware interface is designed to make its own Bean aware. There is only one method, setBeanName(String Name), that retrieves its own ID or name attribute in the Spring container.

BeanFactoryAware

  • The interface has only one method, setBeanFactory(BeanFactory BeanFactory), which gets the BeanFactory in the current environment and can be extended to all beans in the factory.

ApplicationContextAware

  • The interface has only one method, setApplicationContext(ApplicationContext ApplicationContext), which gets the ApplicationContext in the current environment and extends the entire container.

  • Note: Sometimes this interface is not called, depending on your IOC container: Spring IOC containers are required to implement the BeanFactory interface, not the ApplicationContext interface. For containers that do not implement the ApplicationContext interface, Methods defined by the corresponding ApplicationContextAware during the lifecycle are also not called, as long as the container implements the ApplicationContext interface.

BeanPostProcessor

  • PostProcessBeforeInitialization (Object beans, String beanName) : this method is called before initialization, Spring’s AOP is implemented using it.
  • PostProcessAfterInitialization (Object beans, String beanName) : this method is called after the initialization

InitializingBean

  • The interface has only one method, afterPropertiesSet(), which is called after property injection is complete.
  • Any class that inherits this interface executes this method when initializing the bean, doing some property configuration, and so on.
  • InitializingBean is called in the invokeInitMethods(beanName, wrappedBean, MBD) method of the source code for the initialization phase of the lifecycle.

DisposableBean

  • This interface is called when an object is destroyed and can do some resource destruction.
  • DisposableBean similar to InitializingBean, corresponding to the destruction phase of life cycle with ConfigurableApplicationContext# close () method as the entrance, This is done by looping through all beans that have implemented the DisposableBean interface and then calling their destroy() method

Commonly used annotations

@Bean(initMethod = “initMethod”, destroyMethod = “destroyMethod”)

  • @bean Declares a Bean to be used with the @Configuration annotation
  • InitMethod: Declares that the bean initializes a callback to a method that needs to be written by the programmer
  • DestroyMethod: Declare a bean destruction callback to a method that needs to be written by a programmer

@PostConstruct

  • An annotation-based initialization method for a bean

@PreDestroy

  • An annotation-based destruction method for beans

Case analysis

Declare a bean

@Configuration
public class BeanInitAndDestroyConfig {

    / * * *@returnNo bean name is specified; the default is the method name */
    @description (" Test bean life cycle ")
    @Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
    public MyService myServiceBeanName(a) {// The input parameter can inject other dependencies
        return newMyService(); }}Copy the code
  • Declare a bean named myServiceBeanName
  • InitMethod: The bean initialization method is initMethod
  • DestroyMethod: The bean’s destruction method is destroyMethod

Animal implementation class

  • This is just to show that the @qualifier annotation matches the bean name.

My service class

  • That is, for the current beanOnly called onceThe interface of the
/ * * *@Description: Bean life cycle tests: These interfaces are only for the current bean *@Author: jianweil
 * @date: 2021/12/8.so * /
public class MyService implements Person.BeanNameAware.BeanFactoryAware.ApplicationContextAware.InitializingBean.DisposableBean {

    private Animal animal = null;

    private ApplicationContext applicationContext;

    /** * specifies the interface method */
    @Override
    public void service(a) {
        this.animal.use();
    }

    public MyService(a) {
        System.out.println("2. [bean instance] :"+this.getClass().getSimpleName()+"---------- constructor");
    }
    /** * interface specifies methods: inject dependencies */
    @Override
    @Autowired
    @Qualifier("dog")
    public void setAnimal(Animal animal) {
        System.out.println("5. [Bean attribute assignment] : dog---- dependency injection");
        this.animal = animal;
    }


    @Override
    public void setBeanName(String s) {
        System.out.println("6. Call BeanNameAware --setBeanName:"+s);

    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println(7. Call BeanFactoryAware --setBeanFactory);
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        System.out.println("8. Call ApplicationContextAware --setApplicationContext");

    }

    /** * initializes 1 */
    @PostConstruct
    public void myInit(a) {
        System.out.println("10. [Initialization] annotation @postConstruct Custom initialization method [myInit]");
    }

    /** * initializes 2 */
    @Override
    public void afterPropertiesSet(a) throws Exception {
        System.out.println("11. [Initialize] interface InitializingBean method [afterPropertiesSet]");

    }

    /** * initializes 3 */
    public void initMethod(a) {
        System.out.println("12. [initialization] annotation @bean custom initialization method [initMethod]");
    }

    /** * Destroy 1 */
    @PreDestroy
    public void myDestroy(a) {
        System.out.println(14. [Destroy] Annotation @preDestroy Custom destroy method [myDestroy]);
    }

    /** * destroy 2 */
    @Override
    public void destroy(a) throws Exception {
        System.out.println("15. Interface DisposableBean method [destroy]");
    }

    /** * destroy 3 */
    public void destroyMethod(a) {
        System.out.println("16. [destroy] annotation @bean custom destroyMethod [destroyMethod]"); }}Copy the code
  • The interface implemented here only applies to the current bean (that is, the bean defined by @Bean above is named myDefineBeanName) life cycle

Rear processor

  • It is executed once for each bean lifecycle
  • The post-processor is applied to the lifecycle of all beans in the IOC container.
/ * * *@Description: todo
 * @Author: jianweil
 * @date: 2021/12/20 and * /
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class
        beanClass, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = InstantiationAwareBeanPostProcessor - start = = = = = = = = = = = = = = = = = = = = = =");
            System.out.println("1. [container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessBeforeInstantiation () method: beanName"+beanName);
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("3. [container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessAfterInstantiation () method: beanName"+beanName);
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("4. [container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessProperties () method: beanName"+beanName);
            System.out.println("= = = = = = = = = = = = = = = = = = = = = = = = = = = = InstantiationAwareBeanPostProcessor - end = = = = = = = = = = = = = = = = = = = = = =");

        }
        return null; }}Copy the code
/ * * *@Description: post-bean initializer: All beans intercept execution *@Author: jianweil
 * @date: 2021/12/8.so * /
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        // This filters out the beans automatically configured by SpringBoot and prints only the beans of our project
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("9. [container level every bean callback] call BeanPostProcessor. PostProcessBeforeInitialization methods: beanName" + beanName);
        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("myServiceBeanName".equals(beanName) || "dog".equals(beanName)) {
            System.out.println("13. [container level every bean callback] call BeanPostProcessor. PostProcessAfterInitialization methods: beanName" + beanName);
        }
        returnbean; }}Copy the code

Factory rear processor

  • Container level, only one time is allowed
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("0. [container level only call once] call spring BeanFactoryPostProcessor. PostProcessBeanFactory () method." "); }}Copy the code

Output results and interpretation of results

  • “//” is marked for interpretation
// Container-level factory post-processor, called only once immediately after the application context assembs the configuration file
0.[container level only call once] call spring BeanFactoryPostProcessor. PostProcessBeanFactory () method/ / print only because our life process (" myServiceBeanName ". The equals (beanName) | | "dog". The equals (beanName)), all cat only constructor to printCat ---------- construction method/ / # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # dog life cycle of the # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
// Post-processor, container level, for all beans= = = = = = = = = = = = = = = = = = = = = = = = = = = = InstantiationAwareBeanPostProcessor - start = = = = = = = = = = = = = = = = = = = = = =1.[container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessBeforeInstantiation () method: beanName for dog// Instantiate the dogDog ---------- construction method// Post-processor, container level, for all beans
3.[container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessAfterInstantiation () method: beanName for dog// Post-processor, container level, for all beans
4.[container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessProperties () method: BeanName for dog = = = = = = = = = = = = = = = = = = = = = = = = = = = = InstantiationAwareBeanPostProcessor - end = = = = = = = = = = = = = = = = = = = = = =// Post-processor, container level, for all beans
9.[container level every bean callback] call BeanPostProcessor. PostProcessBeforeInitialization methods: beanName for dog// Post-processor, container level, for all beans
13.[container level every bean callback] call BeanPostProcessor. PostProcessAfterInitialization methods: beanName for dog/ / # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # dog bean is complete, start myServiceBeanName# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #


// Post-processor, container level, for all beans= = = = = = = = = = = = = = = = = = = = = = = = = = = = InstantiationAwareBeanPostProcessor - start = = = = = = = = = = = = = = = = = = = = = =1.[container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessBeforeInstantiation () method: beanName myServiceBeanName/ / instantiate
2.[Bean instantiation] : MyService---------- constructor// Post-processor, container level, for all beans
3.[container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessAfterInstantiation () method: beanName myServiceBeanName// Post-processor, container level, for all beans
4.[container level every bean callback] call InstantiationAwareBeanPostProcessor. PostProcessProperties () method: BeanName for myServiceBeanName = = = = = = = = = = = = = = = = = = = = = = = = = = = = InstantiationAwareBeanPostProcessor - end = = = = = = = = = = = = = = = = = = = = = =// Attribute assignment is dependency injection
5.[Bean attribute assignment] : dog---- dependency injection// Bean level, bean: myServiceBeanName implements the interface BeanNameAware
6.Call - BeanNameAware 】 【 setBeanName: myServiceBeanName/ / the bean level
7.Call BeanFactoryAware --setBeanFactory/ / the bean level
8.Call ApplicationContextAware --setApplicationContext// Post-processor, container-level, for all beans: pre-initialization processing
9.[container level every bean callback] call BeanPostProcessor. PostProcessBeforeInitialization methods: beanName myServiceBeanName/ / initialization
10.Initialize annotation@PostConstructCustom initialization method [myInit]11.Interface InitializingBean method [afterPropertiesSet]12.Initialize annotation@BeanCustom initialization methods [initMethod]// Post-processor, container level, for all beans: post-initialization
13.[container level every bean callback] call BeanPostProcessor. PostProcessAfterInitialization methods: beanName myServiceBeanName// When the container environment is loaded, all beans can be used
2021-12-21 11:18:42.994  INFO 18956 --- [           main] c.l.s.SpringbootBeanLifecycleApplication : Started SpringbootBeanLifecycleApplication in 0.719 seconds (JVM running for 1.312)

/ / destroy
14.Destroy notes@PreDestroyCustom destroy method [myDestroy]15.[destroy] Interface DisposableBean16.Destroy notes@BeanDestroyMethod Process Finished with exit code0

Copy the code

Bean life cycle diagram

The point of understanding the Spring life cycle is that you can use beans to do something about them at a given point in their lifetime. Typically, some operations are performed after the Bean is initialized and before it is destroyed.

  • 👍🏻 : have harvest, praise encouragement!
  • ❤️ : Collect articles, easy to look back!
  • 💬 : Comment exchange, mutual progress!