09--Bean的作用域和生命周期

1.Bean的作用域
  • singleton:單例Bean只在容器中存在一個實例,在Spring內部通過HashMap來維護單例bean的緩存
  • prototype:每次索取bean時都會創(chuàng)建一個全新的Bean
  • request:每次請求都會創(chuàng)建一個全新Bean狼忱,該類型作用于Web類型的Spring容器
  • session:每個會話創(chuàng)建一個全新Bean膨疏,該類型作用于Web類型的Spring容器
  • globalSession:類似于session作用域,只是其用于portlet環(huán)境的web應用钻弄。如果在非portlet環(huán)境將視為session作用域
  • 總結:以上就是spring中bean的作用域佃却,其中singleton,prototype屬于Spring bean的基本作作用域窘俺,request饲帅,session,globalSession屬于web應用環(huán)境的作用域瘤泪,必須有web應用環(huán)境的支持
2.Bean的生命周期

20180905094458523.png

  1. IoC容器啟動
  2. 實例化bean
  3. 如果Bean實現了BeanNameAware接口灶泵,則調用setBeanName(String name)返回beanName,該方法不是設置beanName对途,而只是讓Bean獲取自己在BeanFactory配置中的名字
  4. 如果Bean實現BeanFactoryAware接口赦邻,會回調該接口的setBeanFactory(BeanFactory beanFactory)方法,傳入該Bean的BeanFactory实檀,這樣該Bean就獲得了自己所在的BeanFactory
  5. 如果Bean實現了ApplicationContextAware接口惶洲,則調用該接口的setApplicationContext(ApplicationContext applicationContext)方法,設置applicationContext
  6. 如果有Bean實現了BeanPostProcessor接口劲妙,則調用該接口的postProcessBeforeInitialzation(Object bean湃鹊,String beanName)方法,將此BeanPostProcessor應用于給定的新bean實例
  7. 如果Bean實現了InitializingBean接口镣奋,則會回調該接口的afterPropertiesSet()方法
  8. 如果Bean配置了init-method方法币呵,則會執(zhí)行init-method配置的方法
  9. 如果Bean實現了BeanPostProcessor接口,則會回調該接口的postProcessAfterInitialization(Object bean,String beanName)方法
  10. 到此為止余赢,spring中的bean已經可以使用了芯义,這里又涉及到了bean的作用域問題,對于singleton類型的bean妻柒,Spring會將其緩存;對于prototype類型的bean扛拨,不緩存,每次都創(chuàng)建新的bean的實例
  11. 容器關举塔,如果Bean實現了DisposableBean接口绑警,則會回調該接口的destroy()方法銷毀bean,
  12. 如果用戶配置了定destroy-method央渣,則調用自定義方法銷毀bean

來看實際的例子:

  • bean
package com.lyc.cn.v2.day01.lifecycle;

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

public class LifeCycleBean implements
        BeanNameAware,
        BeanFactoryAware,
        ApplicationContextAware,
        InitializingBean,
        DisposableBean {

    // 姓名
    private String name;
    // 年齡
    private int age;

    @Override
    public void setBeanName(String name) {
        System.out.println("01-->BeanNameAware接口被調用了, 獲取到的beanName:" + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("02-->BeanFactoryAware接口被調用了");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("03-->ApplicationContextAware接口被調用了");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("05-->InitializingBean接口被調用了");
    }

    public void myInit() {
        System.out.println("06-->myInit方法被調用了");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("09-->DisposableBean接口被調用了");
    }

    public void myDestroy() {
        System.out.println("10-->自定義destroy-method方法被調動了");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "MyLifeCycleBean{" + "name='" + name + '\'' + ", age=" + age + '}';
    }
}
package com.lyc.cn.v2.day01.lifecycle;

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

public class LifeCycleBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifeCycleBean) {
            System.out.println("04-->調用postProcessBeforeInitialization方法, 獲取到的beanName: " + beanName);
            ((LifeCycleBean) bean).setName("李四");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof LifeCycleBean) {
            System.out.println("07-->調用postProcessAfterInitialization, 獲取到的beanName: " + beanName);
            ((LifeCycleBean) bean).setAge(30);
        }
        return bean;
    }

}
  • xml
<!-- ====================生命周期==================== -->
<!--注意:這里配置的name是張三计盒,age是25,我們會通過beanPostProcessor來修改nage和age -->
<bean id="myLifeCycleBean" class="com.lyc.cn.v2.day01.lifecycle.LifeCycleBean"
      destroy-method="myDestroy"
      init-method="myInit">
    <property name="name" value="張三"/>
    <property name="age" value="25"/>
</bean>
<bean id="myBeanPostProcessor" class="com.lyc.cn.v2.day01.lifecycle.LifeCycleBeanPostProcessor"/>
  • 測試
@Test
public void test13() {
    // 生命周期測試
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("v2/day01.xml");
    LifeCycleBean myLifeCycleBean = applicationContext.getBean("myLifeCycleBean", LifeCycleBean.class);
    System.out.println("08-->bean可以被使用了, beanInfo: " + myLifeCycleBean.toString());
    ((ClassPathXmlApplicationContext) applicationContext).destroy();
}
  • 結果
========測試方法開始=======

01-->BeanNameAware接口被調用了, 獲取到的beanName:myLifeCycleBean
02-->BeanFactoryAware接口被調用了
03-->ApplicationContextAware接口被調用了
04-->調用postProcessBeforeInitialization方法, 獲取到的beanName: myLifeCycleBean
05-->InitializingBean接口被調用了
06-->myInit方法被調用了
07-->調用postProcessAfterInitialization, 獲取到的beanName: myLifeCycleBean
08-->bean可以被使用了, beanInfo: MyLifeCycleBean{name='李四', age=30}
09-->DisposableBean接口被調用了
10-->自定義destroy-method方法被調動了

========測試方法結束=======
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芽丹,隨后出現的幾起案子北启,更是在濱河造成了極大的恐慌,老刑警劉巖拔第,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咕村,死亡現場離奇詭異,居然都是意外死亡蚊俺,警方通過查閱死者的電腦和手機懈涛,發(fā)現死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來春叫,“玉大人肩钠,你說我怎么就攤上這事≡葜常” “怎么了价匠?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長呛每。 經常有香客問我踩窖,道長,這世上最難降的妖魔是什么晨横? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任洋腮,我火速辦了婚禮,結果婚禮上手形,老公的妹妹穿的比我還像新娘啥供。我一直安慰自己,他們只是感情好库糠,可當我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布伙狐。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪贷屎。 梳的紋絲不亂的頭發(fā)上罢防,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天,我揣著相機與錄音唉侄,去河邊找鬼咒吐。 笑死,一個胖子當著我的面吹牛属划,可吹牛的內容都是我干的恬叹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼同眯,長吁一口氣:“原來是場噩夢啊……” “哼妄呕!你這毒婦竟也來了?” 一聲冷哼從身側響起嗽测,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肿孵,沒想到半個月后唠粥,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡停做,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年晤愧,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛉腌。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡官份,死狀恐怖,靈堂內的尸體忽然破棺而出烙丛,到底是詐尸還是另有隱情舅巷,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布河咽,位于F島的核電站钠右,受9級特大地震影響,放射性物質發(fā)生泄漏忘蟹。R本人自食惡果不足惜飒房,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望媚值。 院中可真熱鬧狠毯,春花似錦、人聲如沸褥芒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至惜颇,卻和暖如春皆刺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凌摄。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工羡蛾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锨亏。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓痴怨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親器予。 傳聞我的和親對象是個殘疾皇子浪藻,可洞房花燭夜當晚...
    茶點故事閱讀 44,689評論 2 354

推薦閱讀更多精彩內容