3遭笋、bean生命周期

  • 前面講了bean的創(chuàng)建和注入,這一節(jié)將介紹bean的生命周期徒探。
  • bean的生命周期過程:

bean創(chuàng)建---初始化----銷毀的過程

  • spring中bean的生命周期由容器管理瓦呼,我們可以自定義初始化和銷毀方法;容器在bean進(jìn)行到當(dāng)前生命周期的時(shí)候來調(diào)用我們自定義的初始化和銷毀方法测暗。

一央串、實(shí)現(xiàn)自定義初始化和銷毀方法的幾種方法

1、通過@Bean指定init-method和destroy-method

//1偷溺、定義bean類
public class Car {
    public Car(){
        System.out.println("car constructor...");
    }
    public void init(){
        System.out.println("car ... init...");
    }
    public void detory(){
        System.out.println("car ... detory...");
    }
}
//2蹋辅、配置類中
    @Bean(initMethod="init",destroyMethod="detory")
    public Car car(){
        return new Car();
    }

2、Bean實(shí)現(xiàn)InitializingBean和DisposableBean接口

//1挫掏、實(shí)現(xiàn)InitializingBean和DisposableBean接口
public class Bus implements InitializingBean,DisposableBean {
    
    public Bus(){
        System.out.println("bus constructor...");
    }
    //DisposableBean接口的方法,定義銷毀邏輯
    public void destroy() throws Exception {
        System.out.println("bus...destroy...");
    }
    //InitializingBean接口的方法秩命,定義初始化邏輯
    public void afterPropertiesSet() throws Exception {
        System.out.println("bus...afterPropertiesSet...");
    }

}
//2尉共、配置文件注入bean
@Bean
    public Bus bus() {
        return new Bus();
    }

3、使用@PostConstruct和@PreDestroy注解

@PostConstruct:在bean創(chuàng)建完成并且屬性賦值完成弃锐;來執(zhí)行初始化方法
@PreDestroy:在容器銷毀bean之前通知我們進(jìn)行清理工作

public class Train {
    public Train (){
        System.out.println("train constructor...");
    }
    
    //對(duì)象創(chuàng)建并賦值之后調(diào)用
    @PostConstruct
    public void init(){
        System.out.println("train....@PostConstruct...");
    }
    
    //容器移除對(duì)象之前
    @PreDestroy
    public void detory(){
        System.out.println("train....@PreDestroy...");
    }
}

4袄友、BeanPostProcessor接口,bean的后置處理器

public class MyBeanPostProcessor implements BeanPostProcessor {
    
    //在初始化之前工作(會(huì)環(huán)繞所有的bean)
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
        return bean;
    }
    //在初始化之后工作
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
        return bean;
    }

}

bean生命周期過程總結(jié):

  • 創(chuàng)建
  • BeanPostProcessor.postProcessBeforeInitialization
  • 初始化
  • BeanPostProcessor.postProcessAfterInitialization
  • 銷毀

二霹菊、單實(shí)例和多實(shí)例對(duì)生命周期的影響

  • 構(gòu)建對(duì)象的時(shí)候

單實(shí)例:在容器啟動(dòng)的時(shí)候創(chuàng)建對(duì)象
多實(shí)例:在每次獲取的時(shí)候創(chuàng)建對(duì)象

  • 初始化時(shí)候

對(duì)象創(chuàng)建完成剧蚣,并賦值好,調(diào)用初始化方法

  • 銷毀時(shí)候

單實(shí)例:容器關(guān)閉的時(shí)候
多實(shí)例:容器不會(huì)管理這個(gè)bean旋廷;容器不會(huì)調(diào)用銷毀方法

三鸠按、BeanPostProcessor原理

  • 前面知道BeanPostProcessor是一個(gè)后置處理器接口,源碼:
public interface BeanPostProcessor {
//方法在初始化之前執(zhí)行饶碘,
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//方法在初始化之后執(zhí)行目尖,
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}
  • BeanPostProcessor接口有很多的實(shí)現(xiàn)了,這些實(shí)現(xiàn)類很多非常重要扎运,想bean賦值瑟曲,注入其他組件饮戳,@Autowired,生命周期注解功能洞拨,@Async等等功能的完成都和相應(yīng)的實(shí)現(xiàn)了有關(guān)系扯罐。

1、ApplicationContextAwareProcessor實(shí)現(xiàn)類

  • 繼承該類烦衣,并重寫相應(yīng)的方法可以獲取ApplicationContext對(duì)象
  • 使用:
@Component
public class Train implements ApplicationContextAware {
//通過在實(shí)現(xiàn)ApplicationContextAware在組件bean初始化的時(shí)候傳入
//ApplicationContext篮赢,這樣可以根據(jù)ApplicationContext中的一些數(shù)據(jù)進(jìn)行一些自定義的操作
    private ApplicationContext applicationContext;
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
  • 源碼
class ApplicationContextAwareProcessor implements BeanPostProcessor {

    private final ConfigurableApplicationContext applicationContext;
    private final StringValueResolver embeddedValueResolver;
    /**
     * Create a new ApplicationContextAwareProcessor for the given context.
     */
    public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
    }
//實(shí)現(xiàn)類,在bean初始化之前執(zhí)行
    @Override
    public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
        AccessControlContext acc = null;
//判斷bean是不是屬性系列的aware實(shí)現(xiàn)類
        if (System.getSecurityManager() != null &&
                (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                        bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                        bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
            acc = this.applicationContext.getBeanFactory().getAccessControlContext();
        }

        if (acc != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareInterfaces(bean);
                    return null;
                }
            }, acc);
        }
        else {
//調(diào)用相應(yīng)的aware繼承類
            invokeAwareInterfaces(bean);
        }

        return bean;
    }

    private void invokeAwareInterfaces(Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof EnvironmentAware) {
                ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
            }
            if (bean instanceof EmbeddedValueResolverAware) {
                ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
            }
            if (bean instanceof ResourceLoaderAware) {
                ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
            }
            if (bean instanceof ApplicationEventPublisherAware) {
                ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
            }
            if (bean instanceof MessageSourceAware) {
                ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
            }
            if (bean instanceof ApplicationContextAware) {
                ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
            }
        }
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        return bean;
    }

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末琉挖,一起剝皮案震驚了整個(gè)濱河市启泣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌示辈,老刑警劉巖寥茫,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異矾麻,居然都是意外死亡纱耻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門险耀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弄喘,“玉大人,你說我怎么就攤上這事甩牺∧⒅荆” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵贬派,是天一觀的道長急但。 經(jīng)常有香客問我,道長搞乏,這世上最難降的妖魔是什么波桩? 我笑而不...
    開封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮请敦,結(jié)果婚禮上镐躲,老公的妹妹穿的比我還像新娘。我一直安慰自己侍筛,他們只是感情好萤皂,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勾笆,像睡著了一般敌蚜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窝爪,一...
    開封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天弛车,我揣著相機(jī)與錄音齐媒,去河邊找鬼。 笑死纷跛,一個(gè)胖子當(dāng)著我的面吹牛喻括,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贫奠,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼唬血,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了唤崭?” 一聲冷哼從身側(cè)響起拷恨,我...
    開封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谢肾,沒想到半個(gè)月后腕侄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡芦疏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年冕杠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酸茴。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡分预,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出薪捍,到底是詐尸還是另有隱情笼痹,我是刑警寧澤,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布飘诗,位于F島的核電站与倡,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏昆稿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一息拜、第九天 我趴在偏房一處隱蔽的房頂上張望溉潭。 院中可真熱鬧,春花似錦少欺、人聲如沸喳瓣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽畏陕。三九已至,卻和暖如春仿滔,著一層夾襖步出監(jiān)牢的瞬間惠毁,已是汗流浹背犹芹。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鞠绰,地道東北人腰埂。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像蜈膨,于是被迫代替她去往敵國和親屿笼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

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