深入原始碼理解SpringBean生命週期

DeepSleeping丶發表於2021-05-18

概述

本文描述下Spring的例項化、初始化、銷燬,整個SpringBean生命週期,聊一聊BeanPostProcessor的回撥時機、Aware方法的回撥時機、初始化方法的回撥及其順序、銷燬方法的回撥及其順序、重要的BeanPostProcessor的介紹。
開頭是一張我畫的呼叫流轉圖,然後就是我寫的一個Demo通過日誌列印了SpringBean的生命週期,最後通過原始碼慢慢跟進其生命週期。

生命週期流轉圖

SpringBean生命週期

生命週期Demo

如下對某一個Bean進行getBean操作,最後銷燬上下文,通過日誌來檢視SpringBean的生命週期

程式碼

package com.deepz.spring;

import lombok.extern.slf4j.Slf4j;
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.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Slf4j
@Configuration
public class BeanLifeCycleManager {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(BeanLifeCycleManager.class);
        context.getBean("beanLifeCycle");
        context.close();
    }

    @Bean(initMethod = "init", destroyMethod = "destroyMethod")
    public BeanLifeCycle beanLifeCycle() {
        return new BeanLifeCycle();
    }

    interface MyAware extends ApplicationContextAware, EnvironmentAware, BeanFactoryAware {

    }

    @Component
    static class MyMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {

        @Override
        public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>元資訊收集 ,MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) \nbeanDefinition = [{}]\n,beanType = [{}],beanName = [{}]\n", beanDefinition, beanType, beanName);
            }
        }
    }

    @Component
    static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>例項化前,InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(Class<?> beanClass,String beanName) \nbeanClass = [{}],beanName = [{}]\n", beanClass, beanName);
            }
            return null;
        }

        @Override
        public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>例項化後,InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(Object bean, String beanName)\nbean = [{}],beanName = [{}]\n", bean, beanName);
            }
            return false;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>初始化前,InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization(Object bean, String beanName)\nbean= [{}],beanName = [{}]\n", bean, beanName);
            }
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if ("beanLifeCycle".equals(beanName)) {
                log.info(">>>>>>>>>>初始化後,InstantiationAwareBeanPostProcessor#postProcessAfterInitialization(Object bean, String beanName)\nbean= [{}],beanName = [{}]\n", bean, beanName);
            }
            return bean;
        }
    }

    public static class BeanLifeCycle implements InitializingBean, MyAware, DisposableBean {
        public void init() {
            log.info(">>>>>>>>>>init-method\n");
        }

        @PostConstruct
        public void postConstruct() {
            log.info(">>>>>>>>>>postConstruct\n");
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            log.info(">>>>>>>>>>afterPropertiesSet\n");
        }

        public void destroyMethod() {
            log.info(">>>>>>>>>>destroy-method\n");
        }

        @Override
        public void destroy() {
            log.info(">>>>>>>>>>DisposableBean-destroy\n");
        }

        @PreDestroy
        public void preDestroy(){
            log.info(">>>>>>>>>>preDestroy\n");
        }


        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            log.info(">>>>>>>>>>BeanFactoryAware#setBeanFactory\n");
        }

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            log.info(">>>>>>>>>>ApplicationContextAware#setApplicationContext\n");
        }

        @Override
        public void setEnvironment(Environment environment) {
            log.info(">>>>>>>>>>EnvironmentAware#setEnvironment\n");
        }
    }
}

執行結果

例項化前

從createBean開始,見證Bean的例項化過程,首先是Bean例項化前的一個擴充套件點,它允許你自定義返回Bean例項。(AOP也是在這裡生成代理物件的)

回撥Bean例項化前的方法

AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

主要是為了回撥所有InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation(Class<?> beanClass, String beanName)方法,該方法會返回Object物件,如果返回的Object不為空,則會回撥所有BeanPostProcessor的postProcessAfterInitialization(Object bean, String beanName)方法,那麼返回的Object則會作為Bean去處理,如果返回Null,那麼後續就會交由Spring來例項化、初始化(doCreateBean)。


自定義攔截例項化Bean後回撥Bean後置方法


例項化

AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
如原始碼所示,如果上述擴充套件點沒有return,那麼就會進入到doCreateBean方法

首先是對Bean進行例項化,其中包括了構造器推斷等,本文不過多聊這塊內容,最後會返回BeanWrapper包裹的Bean例項。

元資訊收集

例項化之後Spring通過回撥MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)對一些元資訊做了收集維護處理,如@Autowire、@Resource、@PostConstruct 和 @PreDestroy等,為後續屬性注入做準備。

MergedBeanDefinitionPostProcessor的實現類

MergedBeanDefinitionPostProcessor回撥

初始化

例項化完了,對一些需要收集的資訊也準備好了,後續就是進行屬性注入和回撥初始化方法了,其中populateBean方法是屬性填充,initializeBean是回撥初始化方法。

InstatiationAwareBeanPostProcessor回撥postProcessAfterInstantiation方法

AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)

Aware介面回撥

AbstractAutowireCapableBeanFactory#initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)

部分Aware介面回撥、BeanPostProcessor的初始化前置回撥(包括PostConstruct的呼叫、其餘Aware的回撥)、afterPropertiesSet回撥、自定義init方法回撥、BeanPostProcessor的初始化後置回撥

部分Aware回撥

AbstractAutowireCapableBeanFactory#invokeAwareMethods(final String beanName, final Object bean

BeanPostProcessor的初始化前置回撥

重要BeanPostProcessor如下:

ApplicationContextAwareProcessor#postProcessBeforeInitialization(final Object bean, String beanName)回撥剩餘Aware方法

InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization(final Object bean, String beanName)回撥PostConstruct方法


回撥初始化方法

AbstractAutowireCapableBeanFactory#invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
先回撥InitializingBean的afterPropertiesSet方法,隨後回撥自定義的init-method

BeanPostProcessor的初始化後置回撥

回撥BeanPostProcessor

銷燬

銷燬方法最終會走到DisposableBeanAdapter的destroy方法去做處理,與初始化方法類似,這裡簡單介紹把。
看圖就能發現,順序執行的,先是註解方法,然後是DisposableBean的回撥,最後是自定義的銷燬方法,就是如此簡單。

(小聲)弄了挺久的,如果對你有幫助,或者讓你回憶鞏固相關知識點了,給我點個"支援“鼓勵下..(滑稽),有什麼問題歡迎評論討論。。。

相關文章