容器中Bean的生命週期

    Spring能夠管理singleton做用域Bean的生命週期,Spring能夠精確的知道該Bean什麼時候被建立、什麼時候被初始化完成、容器什麼時候準備銷燬該Bean實列。java

    對於prototype做用域的Bean,Spring容器僅負責建立,當容器建立了Bean實列以後,Bean實列徹底交給客戶端代碼管理,容器再也不跟蹤其生命週期。spring

    對於singleton做用域的Bean,Spring容器知道Bean什麼時候實列化結束、什麼時候銷燬。Spring能夠管理Bean在實列化結束以後和銷燬以前的行爲。管理Bean的生命週期行爲主要有以下兩個時機:app

    1、注入依賴關係後

    Spring提供兩種方式在Bean注入依賴關係後執行特定行爲;ide

 第一:在xml中配置<bean>時,爲其配置init-method屬性,該屬性指定Bean所有依賴關係設置結束後,自動執行該屬性指定的方法;測試

第二:讓Bean類實現InitalizingBean接口,該接口提供public void afterPropertiesSet() throws Exception方法。spa

<!--使用init-method指定Bean注入後執行方法-->
	<bean id="init" class="com.custle.spring.Init" init-method="init"/>
package com.custle.spring;

import org.springframework.beans.factory.InitializingBean;

/**
 * Created by admin on 2018/3/1.
 */
public class Init implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("正在執行初始化方法 afterPropertiesSet()");
    }

    public void init(){
        System.out.println("正在使用init-method屬性指定初始化方法 init()");
    }
}

測試程序:prototype

package com.custle.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by admin on 2018/3/1.
 */
public class BeanFactory {
    public static void main(String[] args) {
        ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
        act.getBean("init");
    }
}

程序輸出:code

正在執行初始化方法 afterPropertiesSet()
正在使用init-method屬性指定初始化方法 init()

 能夠看見,當同時使用這兩種方式初始化方法時,先執行InitializingBean接口中定義的方法,而後執行init-method屬性指定的方法。使用InitializingBean接口的方式代碼耦合性較高。xml

    2、Bean銷燬以前的行爲

    與定製初始化行爲類似,Spring也提供了兩種方式定製Bean銷燬以前的特定行爲,這兩種方式以下:接口

    第一:在xml中配置<bean>時使用destory-method屬性;

    第二:實現DisposableBean接口;

<!--使用destory-method指定Bean銷燬前執行方法-->
	<bean id="destory" class="com.custle.spring.Destory" destroy-method="close"/>
package com.custle.spring;

import org.springframework.beans.factory.DisposableBean;

/**
 * Created by admin on 2018/3/1.
 */
public class Destory implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("正在經過實現DisposableBean接口執行Bean銷燬前的destroy()方法");
    }

    public void close(){
        System.out.println("正在經過destory-method執行Bean銷燬前的close()方法");
    }
}

測試程序:

package com.custle.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by admin on 2018/3/1.
 */
public class BeanFactory {
    public static void main(String[] args) {
        ApplicationContext act = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
        act.getBean("destory");
    }
}

控制檯輸出:

正在使用init-method屬性指定初始化方法 init()

能夠看見當同時使用這兩種方式執行Bean銷燬前行爲時,只有經過init-method屬性配置的方式生效了。這是爲何呢?單列Bean的生命週期隨着Spring容器的關閉而銷燬,若是在一個非WEB應用環境下,爲了讓Spring容器優雅的關閉,並調用singleton Bean上相應的析構回調方法,則須要在JVM中註冊一個關閉鉤子,這樣就能夠保證Spring容器被恰當關閉。

使用以下測試程序:

package com.custle.spring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Created by admin on 2018/3/1.
 */
public class BeanFactory {
    public static void main(String[] args) {
        AbstractApplicationContext act = new ClassPathXmlApplicationContext("applicationContext-spring.xml");
        act.getBean("destory");
        act.registerShutdownHook();
    }
}

控制檯輸出:

正在經過實現DisposableBean接口執行Bean銷燬前的destroy()方法
正在經過destory-method執行Bean銷燬前的close()方法

能夠看見當這兩種方式同時執行時,經過實現DisposableBean接口執行銷燬Bean前的行爲優先級更高。

    除此以外,若是容器中不少Bean都須要指定特定的生命週期行爲,則能夠在<beans>中設置default-init-method屬性和default-destory-method屬性,它們的做用和init-method、destory-method屬性相似,只不過它們是對該<beans>下全部的bean都生效。

    當Bean實現了ApplicationContextAware接口、BeanNameAware接口以後,Spring容器會在該Bean初始化完成以後--也就是調用init-method屬性所指定的方法(若是有)以後,再回調setApplicationConetext(ApplicationContext applicationConext)、setBeanName(String name)方法。

相關文章
相關標籤/搜索