Spring的ioc容器功能很是強大,負責Spring的Bean的建立和管理等功能。而Spring 的bean是整個Spring應用中很重要的一部分,瞭解Spring Bean的生命週期對咱們瞭解整個spring框架會有很大的幫助。 BeanFactory和ApplicationContext是Spring兩種很重要的容器,前者提供了最基本的依賴注入的支持,然後者在繼承前者的基礎進行了功能的拓展,例如增長了事件傳播,資源訪問和國際化的消息訪問等功能。本文主要介紹了ApplicationContext和BeanFactory兩種容器的Bean的生命週期。
ApplicationContext容器中,Bean的生命週期流程如上圖所示,流程大體以下:java
1.首先容器啓動後,會對scope爲singleton且非懶加載的bean進行實例化,spring
2.按照Bean定義信息配置信息,注入全部的屬性,緩存
3.若是Bean實現了BeanNameAware接口,會回調該接口的setBeanName()方法,傳入該Bean的id,此時該Bean就得到了本身在配置文件中的id,ruby
4.若是Bean實現了BeanFactoryAware接口,會回調該接口的setBeanFactory()方法,傳入該Bean的BeanFactory,這樣該Bean就得到了本身所在的BeanFactory,app
5.若是Bean實現了ApplicationContextAware接口,會回調該接口的setApplicationContext()方法,傳入該Bean的ApplicationContext,這樣該Bean就得到了本身所在的ApplicationContext,框架
6.若是有Bean實現了BeanPostProcessor接口,則會回調該接口的postProcessBeforeInitialzation()方法,函數
7.若是Bean實現了InitializingBean接口,則會回調該接口的afterPropertiesSet()方法,post
8.若是Bean配置了init-method方法,則會執行init-method配置的方法,this
9.若是有Bean實現了BeanPostProcessor接口,則會回調該接口的postProcessAfterInitialization()方法,spa
10.通過流程9以後,就能夠正式使用該Bean了,對於scope爲singleton的Bean,Spring的ioc容器中會緩存一份該bean的實例,而對於scope爲prototype的Bean,每次被調用都會new一個新的對象,期生命週期就交給調用方管理了,再也不是Spring容器進行管理了
11.容器關閉後,若是Bean實現了DisposableBean接口,則會回調該接口的destroy()方法,
12.若是Bean配置了destroy-method方法,則會執行destroy-method配置的方法,至此,整個Bean的生命週期結束
咱們定義了一個Person類,該類實現了
BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean,DisposableBean五個接口,而且在applicationContext.xml文件中配置了該Bean的id爲person1,而且配置了init-method和destroy-method,爲該Bean配置了屬性name爲jack的值,而後定義了一個MyBeanPostProcessor方法,該方法實現了BeanPostProcessor接口,且在applicationContext.xml文件中配置了該方法的Bean,其代碼以下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="person1" destroy-method="myDestroy" init-method="myInit" class="com.test.spring.life.Person">
<property name="name">
<value>jack</value>
</property>
</bean>
<!-- 配置自定義的後置處理器 -->
<bean id="postProcessor" class="com.pingan.spring.life.MyBeanPostProcessor" />
</beans>
public class Person implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean { private String name; public Person() { System.out.println("PersonService類構造方法"); } public String getName() { return name; } public void setName(String name) { this.name = name; System.out.println("set方法被調用"); } //自定義的初始化函數
public void myInit() { System.out.println("myInit被調用"); } //自定義的銷燬方法
public void myDestroy() { System.out.println("myDestroy被調用"); } public void destroy() throws Exception { // TODO Auto-generated method stub
System.out.println("destory被調用"); } public void afterPropertiesSet() throws Exception { // TODO Auto-generated method stub
System.out.println("afterPropertiesSet被調用"); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { // TODO Auto-generated method stub
System.out.println("setApplicationContext被調用"); } public void setBeanFactory(BeanFactory beanFactory) throws BeansException { // TODO Auto-generated method stub
System.out.println("setBeanFactory被調用,beanFactory"); } public void setBeanName(String beanName) { // TODO Auto-generated method stub
System.out.println("setBeanName被調用,beanName:" + beanName); } public String toString() { return "name is :" + name; }
public class MyBeanPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub
System.out.println("postProcessBeforeInitialization被調用"); return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { // TODO Auto-generated method stub
System.out.println("postProcessAfterInitialization被調用"); return bean; } }
public class AcPersonServiceTest { public static void main(String[] args) { // TODO Auto-generated method stub
System.out.println("開始初始化容器"); ApplicationContext ac = new ClassPathXmlApplicationContext("com/test/spring/life/applicationContext.xml"); System.out.println("xml加載完畢"); Person person1 = (Person) ac.getBean("person1"); System.out.println(person1); System.out.println("關閉容器"); ((ClassPathXmlApplicationContext)ac).close(); } }
咱們啓動容器,能夠看到整個調用過程:
開始初始化容器 九月 25, 2016 10:44:50 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@b4aa453: startup date [Sun Sep 25 22:44:50 CST 2016]; root of context hierarchy 九月 25, 2016 10:44:50 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [com/test/spring/life/applicationContext.xml] Person類構造方法 set方法被調用 setBeanName被調用,beanName:person1 setBeanFactory被調用,beanFactory setApplicationContext被調用 postProcessBeforeInitialization被調用 afterPropertiesSet被調用 myInit被調用 postProcessAfterInitialization被調用 xml加載完畢 name is :jack 關閉容器 九月 25, 2016 10:44:51 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@b4aa453: startup date [Sun Sep 25 22:44:50 CST 2016]; root of context hierarchy destory被調用 myDestroy被調用
BeanFactoty容器中, Bean的生命週期如上圖所示,與ApplicationContext相比,有以下幾點不一樣:
1.BeanFactory容器中,不會調用ApplicationContextAware接口的setApplicationContext()方法,
2.BeanPostProcessor接口的postProcessBeforeInitialzation()方法和postProcessAfterInitialization()方法不會自動調用,必須本身經過代碼手動註冊
3.BeanFactory容器啓動的時候,不會去實例化全部Bean,包括全部scope爲singleton且非懶加載的Bean也是同樣,而是在調用的時候去實例化。
咱們仍是使用前面定義好的Person類和MyBeanPostProcessor類,以及ApplicationContext.xml文件,main函數實現以下:
public class BfPersonServiceTest { public static void main(String[] args) { // TODO Auto-generated method stub
System.out.println("開始初始化容器"); ConfigurableBeanFactory bf = new XmlBeanFactory(new ClassPathResource("com/pingan/spring/life/applicationContext.xml")); System.out.println("xml加載完畢"); //beanFactory須要手動註冊beanPostProcessor類的方法
bf.addBeanPostProcessor(new MyBeanPostProcessor()); Person person1 = (Person) bf.getBean("person1"); System.out.println(person1); System.out.println("關閉容器"); bf.destroySingletons(); } }
啓動容器,咱們能夠看到整個調用流程:
開始初始化容器 九月 26, 2016 12:27:05 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [com/pingan/spring/life/applicationContext.xml] xml加載完畢 PersonService類構造方法 set方法被調用 setBeanName被調用,beanName:person1 setBeanFactory被調用,beanFactory postProcessBeforeInitialization被調用 afterPropertiesSet被調用 myInit被調用 postProcessAfterInitialization被調用 name is :jack 關閉容器 destory被調用 myDestroy被調用