Spring Bean生命周期-階段匯總觅丰,面試必備(十二)

以后面試問(wèn)到Bean的生命周期再也不怕了妨退!

看了這么久的Spring源碼咬荷,想必對(duì)Spring的生命周期已經(jīng)有了一定的了解,這次將之前零散的生命周期處理的事情貫穿起來(lái)懦底,看過(guò)之后基茵,一定對(duì)bean的生命周期有更深入的理解

與文無(wú)關(guān)

簡(jiǎn)介

  1. 實(shí)例化
  2. 設(shè)置bean的Aware
  3. BeanPostProcessor.postProcessBeforeInitialization(Object bean, String beanName)
  4. InitializingBean.afterPorpertiesSet
  5. BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName)
  6. SmartInitializingSingleton.afterSingletonsInstantiated
  7. SmartLifecycle.start
  8. bean已經(jīng)在spring容器的管理下,可以做我們想做的事
  9. SmartLifecycle.stop(Runnable callback)
  10. DisposableBean.destroy()

細(xì)節(jié)部分

  1. 實(shí)例化對(duì)應(yīng)代碼宴咧,使用合適的初始化方案來(lái)創(chuàng)建一個(gè)新的bean實(shí)例掺栅,factory-method,或者構(gòu)造器注入桃笙,或者簡(jiǎn)單的直接實(shí)例化

實(shí)例化策略類:
InstantiationStrategy

實(shí)例化具體方法:
AbstractAutowireCapableBeanFactory.createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args)

  1. 設(shè)置bean的Aware沙绝。InitializingBean.afterPorpertiesSet搏明,BeanPostProcessor對(duì)bean的加工處理基本上在一塊出現(xiàn)。

設(shè)置Aware方法順序:

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware

BeanPostProcessor.postProcessBeforeInitialization


image.png

ApplicationContextAwareProcessor也會(huì)設(shè)置Aware:

  • EnvironmentAware
  • EmbeddedValueResolverAware
  • ResourceLoaderAware
  • ApplicationEventPublisherAware
  • MessageSourceAware
  • ApplicationContextAware

調(diào)用afterpropertiesSet方法:位于AbstractAutowireCapableBeanFactory.invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)方法中

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        
      // 設(shè)置Aware  
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }
        
      //BeanPostProcessor的postProcessBeforeInitialization  
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
           //調(diào)用init方法闪檬,其判斷是否是InitializingBean的實(shí)例星著,然后調(diào)用afterPropertiesSet
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
    
      //BeanPostProcessor的postProcessAfterInitialization  
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }
  1. SmartInitializingSingleton.afterSingletonsInstantiated的調(diào)用位置

DefaultListableBeanFactory.preInstantiateSingletons方法,其在所有的bean都實(shí)例化完成之后調(diào)用

@Override
    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        // Iterate over a copy to allow for init methods which in turn register new bean definitions.
        // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
        List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

        // Trigger initialization of all non-lazy singleton beans...
        // 觸發(fā)實(shí)例化所有的非懶加載的單例
        for (String beanName : beanNames) {
           ...
        }

        // Trigger post-initialization callback for all applicable beans...
        // 觸發(fā)應(yīng)用bean的post-initialization回調(diào)粗悯,也就是afterSingletonsInstantiated方法
        for (String beanName : beanNames) {
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged(new PrivilegedAction<Object>() {
                        @Override
                        public Object run() {
                            smartSingleton.afterSingletonsInstantiated();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }
  1. SmartLifecycle.start在ApplicationContext結(jié)束刷新finishRefresh時(shí)虚循,getLifecycleProcessor().onRefresh();

判斷bean是否為SmartLifecycle并且autoStartup样傍。

位于:
DefaultLifecycleProcessor.onRefresh

  1. stop方法在Application.close的時(shí)候横缔,調(diào)用getLifecycleProcessor().stop()方法仍然在DefaultLifecycleProcessor內(nèi)部
  1. DisposableBean.destroy方法,doCreateBean方法中會(huì)判斷bean是否有銷(xiāo)毀相關(guān)操作衫哥,實(shí)現(xiàn)了DisposableBean方法或定義了銷(xiāo)毀方法茎刚。

AbstractAutowireCapableBeanFactory.doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

代碼演示

public class HelloWorld implements SmartInitializingSingleton,SmartLifecycle,InitializingBean,
        DisposableBean,MyInterface,BeanNameAware,ApplicationContextAware
{

    private final Log logger = LogFactory.getLog(getClass());
    private boolean isRunning;
    

    public HelloWorld() {
        System.out.println("實(shí)例化");
    }

    public void sayHello(){
        System.out.println("hello World");
    }

    public void afterSingletonsInstantiated() {
        System.out.println("SmartInitializingSingleton afterSingletonsInstantiated");
    }

    public void start() {
        isRunning = true;
        System.out.println("LifeCycle start");
    }

    public void stop() {
        System.out.println("LifeCycle stop");
    }

    public boolean isRunning() {
        return isRunning;
    }

    public boolean isAutoStartup() {
        return true;
    }

    public void stop(Runnable callback) {
        System.out.println("LifeScycle stop");
        callback.run();
    }

    public int getPhase() {
        return 0;
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("afterproperties set");
    }

    public void destroy() throws Exception {
        System.out.println("destroy");
    }

    public void my(String str) {
        System.out.println(str);
    }

    public void setBeanName(String name) {
        System.out.println("set bean Name aware");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("set Application Aware");
    }
}


//MyInterface接口
public interface MyInterface {
    void my(String str);
}


//app.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="porcessor" class="me.aihe.MyBeanPostProcessor" />
    <bean id="hello" class="me.aihe.HelloWorld">

    </bean>
</beans>



//SpringApp
public class SpringApp {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("app.xml");
        HelloWorld hello = (HelloWorld) applicationContext.getBean("hello");
        hello.sayHello();
        applicationContext.close();
    }
}

運(yùn)行結(jié)果:


最后

可對(duì)照源代碼自行驗(yàn)證生命周期。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炕檩,一起剝皮案震驚了整個(gè)濱河市斗蒋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌笛质,老刑警劉巖泉沾,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異妇押,居然都是意外死亡跷究,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)敲霍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)俊马,“玉大人,你說(shuō)我怎么就攤上這事肩杈〔裎遥” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵扩然,是天一觀的道長(zhǎng)艘儒。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么界睁? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任觉增,我火速辦了婚禮,結(jié)果婚禮上翻斟,老公的妹妹穿的比我還像新娘逾礁。我一直安慰自己,他們只是感情好访惜,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布嘹履。 她就那樣靜靜地躺著,像睡著了一般疾牲。 火紅的嫁衣襯著肌膚如雪植捎。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天阳柔,我揣著相機(jī)與錄音焰枢,去河邊找鬼。 笑死舌剂,一個(gè)胖子當(dāng)著我的面吹牛济锄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播霍转,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼荐绝,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了避消?” 一聲冷哼從身側(cè)響起低滩,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎岩喷,沒(méi)想到半個(gè)月后恕沫,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纱意,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年婶溯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偷霉。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡迄委,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出类少,到底是詐尸還是另有隱情叙身,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布硫狞,位于F島的核電站信轿,受9級(jí)特大地震影響赞警,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜虏两,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望世剖。 院中可真熱鬧定罢,春花似錦、人聲如沸旁瘫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)酬凳。三九已至惠况,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宁仔,已是汗流浹背稠屠。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留翎苫,地道東北人权埠。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像煎谍,于是被迫代替她去往敵國(guó)和親攘蔽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容