Spring Boot Bean生命周期

注:Spring Boot Bean的生命周期,什么是Bean的生命周期,就是Bean從創(chuàng)建到銷毀的過程。

Bean的生命周期過程描述

我們先看一下Bean的生命周期過程中都會(huì)經(jīng)歷些什么,我先簡(jiǎn)單解釋一下,后面我們通過源碼進(jìn)行詳細(xì)解釋。首先Spring在實(shí)例化Bean的時(shí)候,會(huì)先調(diào)用它的構(gòu)造函數(shù),進(jìn)行Bean的實(shí)例化,然后進(jìn)行Bean的初始化,Bean的初始化經(jīng)過三個(gè)階段初始化之前(applyBeanPostProcessorsBeforeInitialization),其次是進(jìn)行初始化(invokeInitMethods),最后是初始化之后(postProcessAfterInitialization),這就是Bean的初始化過程;然后就開始利用Bean進(jìn)行業(yè)務(wù)邏輯處理,最后容器正常關(guān)閉,Spring開始銷毀Bean,Bean的銷毀過程相對(duì)比較簡(jiǎn)單,調(diào)用DisposableBeanAdapter.destroy()方法,該方法中有三個(gè)地方比較重要,分別觸發(fā)Bean的生命周期方法,它們是:processor.postProcessBeforeDestruction(this.bean, this.beanName);
((DisposableBean) bean).destroy();
invokeCustomDestroyMethod(this.destroyMethod);

下面我把用圖片來進(jìn)行直觀展示:

Bean的生命周期.png

實(shí)例運(yùn)行

User類,這里就是普通的一個(gè)Bean,用來添加到容器中,觀察其生命周期

package com.itbofeng.bean;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class User implements InitializingBean , DisposableBean {
    private String name;
    public User() {
        System.out.println("調(diào)用Bean的函數(shù)(constructor)");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        System.out.println("調(diào)用Bean的函數(shù)(setName/setAttribute)");
        this.name = name;
    }
    @PostConstruct
    public void postConstruct(){
        System.out.println("調(diào)用Bean的函數(shù)(postConstruct)");
    }
    //MainConfig中@Bean 的initMethod
    public void initMethod(){
        System.out.println("調(diào)用Bean的函數(shù)(initMethod)");
    }
    //InitializingBean接口的方法afterPropertiesSet
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("調(diào)用Bean的函數(shù)(afterPropertiesSet)");
    }
    @PreDestroy
    public void preDestroy(){
        System.out.println("調(diào)用Bean的函數(shù)(preDestroy)");
    }
    //DisposableBean接口的方法destroy
    @Override
    public void destroy() throws Exception {
        System.out.println("調(diào)用Bean的函數(shù)(destroy)");
    }
    //MainConfig中@Bean 的destroyMethod
    public void destroyMethod(){
        System.out.println("調(diào)用Bean的函數(shù)(destroyMethod)");
    }
}

CustomBeanPostProcessor類,用來觀察BeanPostProcessor的運(yùn)行時(shí)期

package com.itbofeng.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    @Nullable
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(bean.getClass()==User.class){
            System.out.println("調(diào)用postProcessBeforeInitialization...");
        }
        return bean;
    }
    @Nullable
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean.getClass()==User.class){
            System.out.println("調(diào)用postProcessAfterInitialization...");
        }
        return bean;
    }
}

MainConfig類,SpringBoot程序運(yùn)行的主類,并將User和CustomBeanPostProcessor 加入到容器中

package com.itbofeng;
import com.itbofeng.bean.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class MainConfig {
    public static void main(String[] args) {
        SpringApplication.run(MainConfig.class,args);
    }
    @Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
    public User user(){
        return new User();
    }
}

運(yùn)行結(jié)果查看


運(yùn)行結(jié)果.png

源碼解析

初始化過程
首先我們將斷點(diǎn)打到CustomBeanPostProcessor.postProcessBeforeInitialization的第一行代碼,然后我看一下其方法調(diào)用棧:


方法調(diào)用棧.png

主要包括兩個(gè)地方,一個(gè)是容器刷新,第二個(gè)是初始化Bean,我們先對(duì)這容器刷新的源碼進(jìn)行簡(jiǎn)單查看

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }

            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }
    }

注意finishBeanFactoryInitialization,上面說明也解釋說該方法的作用是初始化所有剩下的非懶加載的單例Bean,從該描述也可以知道,懶加載和原型的Bean在該階段并不會(huì)被加載,這部分代碼是Spring容器刷新時(shí)的代碼,也是Spring IOC比較核心的代碼,在學(xué)習(xí)后面中,慢慢將該部分的代碼慢慢學(xué)習(xí),接下來我們看一下初始化Bean部分的代碼:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    //對(duì)實(shí)現(xiàn)了Aware接口的方法進(jìn)行執(zhí)行,方法就在下方,使用方法直接實(shí)現(xiàn)對(duì)應(yīng)的Aware接口即可
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //執(zhí)行實(shí)現(xiàn)了BeanPostProcessor的postProcessBeforeInitialization方法
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        //執(zhí)行初始化方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        //執(zhí)行實(shí)現(xiàn)了BeanPostProcessor的postProcessAfterInitialization方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
            throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        //調(diào)用InitializingBean的afterPropertiesSet方法
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
    //調(diào)用@Bean制定的的initMethod方法
    if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

以上就是初始化階段,我們會(huì)發(fā)現(xiàn)初始化過程中沒有@PostConstruct注解標(biāo)注的方法,那是因?yàn)閷?duì)@PostConstruct的處理也是BeanPostProcessor的實(shí)現(xiàn)類InitDestroyAnnotationBeanPostProcessor,那么我們就應(yīng)該有疑問為什么InitDestroyAnnotationBeanPostProcessor.postProcessBeforeDestruction為什么會(huì)在CustomBeanPostProcessor.postProcessBeforeInitialization之后進(jìn)行,是因?yàn)槿绻恢付樞蚰J(rèn)我們的getOrder為0,而InitDestroyAnnotationBeanPostProcessor的getOrder為Ordered.LOWEST_PRECEDENCE=2147483647,getOrder越大則,優(yōu)先級(jí)越低,所以我們自定義的在其之前,至此初始化部分結(jié)束。
下面我們簡(jiǎn)單看一下銷毀階段:

public void destroy() {
    //處理@PreDestroy注解注釋的方法
    if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
        for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
            processor.postProcessBeforeDestruction(this.bean, this.beanName);
        }
    }
    //處理實(shí)現(xiàn)了DisposableBean接口的destroy的方法
    if (this.invokeDisposableBean) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
        }
        try {
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((DisposableBean) bean).destroy();
                    return null;
                }, acc);
            }
            else {
                ((DisposableBean) bean).destroy();
            }
        }
        catch (Throwable ex) {
            String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
            if (logger.isDebugEnabled()) {
                logger.warn(msg, ex);
            }
            else {
                logger.warn(msg + ": " + ex);
            }
        }
    }
    //處理@Bean指定的destroyMethod方法
    if (this.destroyMethod != null) {
        invokeCustomDestroyMethod(this.destroyMethod);
    }
    else if (this.destroyMethodName != null) {
        Method methodToCall = determineDestroyMethod(this.destroyMethodName);
        if (methodToCall != null) {
            invokeCustomDestroyMethod(methodToCall);
        }
    }
}

結(jié)束語(yǔ)

至此,我們Bean的生命周期探索初步結(jié)束,后面再做進(jìn)一步深入學(xué)習(xí),在學(xué)習(xí)本節(jié)課時(shí)要多進(jìn)行調(diào)試,斷點(diǎn)跟蹤,會(huì)更加有效果。另外無論是在初始化還是在結(jié)束時(shí)都是處理的單例的Bean,而且在初始化時(shí),處理的Bean還是非懶加載的,所以需要特殊說明:非懶加載的單實(shí)例Bean的生命周期如上;懶加載的單實(shí)例Bean是在第一次獲取進(jìn)行初始化過程;原型Bean是在每次獲取時(shí)都進(jìn)行初始化,而且Spring容器不會(huì)管理器銷毀。
最近在網(wǎng)上看到了一篇文章,很不錯(cuò),詳細(xì)的介紹了Spring IOC的原理,如果大家想詳細(xì)了解Spring的IOC可以看一下:https://www.cnblogs.com/ITtangtang/p/3978349.html,好東西大家一起分享,????????????????????????????????

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.1 spring IoC容器和beans的簡(jiǎn)介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,851評(píng)論 2 22
  • 1.1 Spring IoC容器和bean簡(jiǎn)介 本章介紹了Spring Framework實(shí)現(xiàn)的控制反轉(zhuǎn)(IoC)...
    起名真是難閱讀 2,674評(píng)論 0 8
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,656評(píng)論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,282評(píng)論 6 342
  • 在深圳樸門看狗2014-8-28 (早幾天回來時(shí)寫的,存在電腦里,忘了發(fā)出來。今兒發(fā)出來分享吧。) 清 早起來,妞...
    阿緣閱讀 177評(píng)論 0 0

友情鏈接更多精彩內(nèi)容