Spring中bean生命週期詳細歸納

語言: CN / TW / HK

前言

關於Spring的IOC容器中Bean的生命週期問題在各種面試或者實際開發中經常會遇到,能準確無誤簡述出來的人比較少,在實際開發中我們會根據Spring 託管Bean的在不同時間段做些高階拓展操作達到使用目的,本文闡述下Spring的Bean全生命週期,供在面試者或者在實際開發中需要的人進行認識與理解。

Bean完整生命週期

在傳統的Java應用中,bean的生命週期很簡單,使用Java關鍵字 new 進行Bean 的例項化,然後該Bean 就能夠使用了。一旦bean不再被使用,則由Java自動進行垃圾回收。相比之下,Spring管理Bean的生命週期就複雜多了,正確理解Bean 的生命週期非常重要,因為Spring對Bean的管理可擴充套件性非常強,下面展示了一個Bean的構造過程.如圖

build-sub

如上圖所示,Bean 的生命週期還是比較複雜的。下面採用文字對每一步進行描述

  1. Spring啟動,查詢並載入需要被Spring管理的bean,進行Bean的例項化
  2. Bean例項化後對將Bean的引入和值注入到Bean的屬性中
  3. 如果Bean實現了BeanNameAware介面的話,Spring將Bean的Id傳遞給setBeanName()方法
  4. 如果Bean實現了BeanFactoryAware介面的話,Spring將呼叫setBeanFactory()方法,將BeanFactory容器例項傳入
  5. 如果Bean實現了ApplicationContextAware介面的話,Spring將呼叫Bean的setApplicationContext()方法,將bean所在應用上下文引用傳入進來
  6. 如果Bean實現了BeanPostProcessor介面,Spring就將呼叫他們的postProcessBeforeInitialization()方法。
  7. 如果Bean 實現了InitializingBean介面,Spring將呼叫他們的afterPropertiesSet()方法。類似的,如果bean使用init-method聲明瞭初始化方法,該方法也會被呼叫
  8. 如果Bean 實現了BeanPostProcessor介面,Spring就將呼叫他們的postProcessAfterInitialization()方法。
  9. 此時,Bean已經準備就緒,可以被應用程式使用了。他們將一直駐留在應用上下文中,直到應用上下文被銷燬。
  10. 如果bean實現了DisposableBean介面,Spring將呼叫它的destory()介面方法,同樣,如果bean使用了destory-method 宣告銷燬方法,該方法也會被呼叫。

上面是Spring 中Bean的核心介面和生命週期,面試回答上述過程已經足夠了。但是翻閱JavaDoc文件發現除了以上介面外,還有另外的初始化過程涉及的介面:摘自org.springframework.beans.factory.BeanFactory, 全部相關介面如下,上述已有的就不用著重標註,把額外的相關介面著重標註下.如圖:

bean-interface

如上圖所示對bean生命週期進行更加完整描述,下文詳細闡述下過程.

初始化

  • BeanNameAware.setBeanName() 在建立此bean的bean工廠中設定bean的名稱,在普通屬性設定之後呼叫,在InitializinngBean.afterPropertiesSet()方法之前呼叫
  • BeanClassLoaderAware.setBeanClassLoader(): 在普通屬性設定之後,InitializingBean.afterPropertiesSet()之前呼叫
  • BeanFactoryAware.setBeanFactory() : 回撥提供了自己的bean例項工廠,在普通屬性設定之後,在InitializingBean.afterPropertiesSet()或者自定義初始化方法之前呼叫
  • EnvironmentAware.setEnvironment(): 設定environment在元件使用時呼叫
  • EmbeddedValueResolverAware.setEmbeddedValueResolver(): 設定StringValueResolver 用來解決嵌入式的值域問題
  • ResourceLoaderAware.setResourceLoader(): 在普通bean物件之後呼叫,在afterPropertiesSet 或者自定義的init-method 之前呼叫,在 ApplicationContextAware 之前呼叫。
  • ApplicationEventPublisherAware.setApplicationEventPublisher(): 在普通bean屬性之後呼叫,在初始化呼叫afterPropertiesSet 或者自定義初始化方法之前呼叫。在 ApplicationContextAware 之前呼叫。
  • MessageSourceAware.setMessageSource(): 在普通bean屬性之後呼叫,在初始化呼叫afterPropertiesSet 或者自定義初始化方法之前呼叫,在 ApplicationContextAware 之前呼叫。
  • ApplicationContextAware.setApplicationContext(): 在普通Bean物件生成之後呼叫,在InitializingBean.afterPropertiesSet之前呼叫或者使用者自定義初始化方法之前。在ResourceLoaderAware.setResourceLoader,ApplicationEventPublisherAware.setApplicationEventPublisher,MessageSourceAware之後呼叫。
  • ServletContextAware.setServletContext(): 執行時設定ServletContext,在普通bean初始化後呼叫,在InitializingBean.afterPropertiesSet之前呼叫,在 ApplicationContextAware 之後呼叫注:是在WebApplicationContext 執行時
  • BeanPostProcessor.postProcessBeforeInitialization() : 將此BeanPostProcessor 應用於給定的新bean例項 在任何bean初始化回撥方法(像是InitializingBean.afterPropertiesSet或者自定義的初始化方法)之前呼叫。這個bean將要準備填充屬性的值。返回的bean示例可能被普通物件包裝,預設實現返回是一個bean。
  • BeanPostProcessor.postProcessAfterInitialization() : 將此BeanPostProcessor 應用於給定的新bean例項 在任何bean初始化回撥方法(像是InitializingBean.afterPropertiesSet或者自定義的初始化方法)之後呼叫。這個bean將要準備填充屬性的值。返回的bean示例可能被普通物件包裝
  • InitializingBean.afterPropertiesSet(): 被BeanFactory在設定所有bean屬性之後呼叫(並且滿足BeanFactory 和 ApplicationContextAware)。

銷燬

在BeanFactory 關閉的時候,Bean的生命週期會呼叫如下方法:

  • DestructionAwareBeanPostProcessor.postProcessBeforeDestruction(): 在銷燬之前將此BeanPostProcessor 應用於給定的bean例項。能夠呼叫自定義回撥,像是DisposableBean 的銷燬和自定義銷燬方法,這個回撥僅僅適用於工廠中的單例bean(包括內部bean)
  • 實現了自定義的destory()方法