Spring能夠管理singleton做用域Bean的生命週期,Spring能夠精確的知道該Bean什麼時候被建立、什麼時候被初始化完成、容器什麼時候準備銷燬該Bean實列。java
對於prototype做用域的Bean,Spring容器僅負責建立,當容器建立了Bean實列以後,Bean實列徹底交給客戶端代碼管理,容器再也不跟蹤其生命週期。spring
對於singleton做用域的Bean,Spring容器知道Bean什麼時候實列化結束、什麼時候銷燬。Spring能夠管理Bean在實列化結束以後和銷燬以前的行爲。管理Bean的生命週期行爲主要有以下兩個時機:app
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
與定製初始化行爲類似,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)方法。