Spring容器是個神奇的魔法師,瞧!我們把寫好的類和組態檔放進Spring容器里,Spring容器就能變出各種各樣的Bean,之后,各種各樣的Bean存在Spring容器里,相互依賴,彼此合作,又構成一個繁忙的應用程式,處理著來自遠方的各種請求;直到應用程式退出,Spring容器關閉,Bean才消失在歷史的長河中,由此可見,存在Spring容器里的Bean有個從誕生到消亡的程序,這個程序俗稱Bean的生命周期,具體如下:
01.運行Web應用程式
02.創建Spring容器
03.加載組態檔生成Bean的定義
04.創建實作了BeanFactoryPostProcessor介面的Bean,呼叫postProcessBeanFactory方法
05.創建實作了BeanPostProcessor介面的Bean
06.創建其它型別的Bean
07.通過屬性注入依賴
08.呼叫Aware介面的方法
09.呼叫postProcessBeforeInitialization方法
10.呼叫afterPropertiesSet方法初始化Bean
11.呼叫postProcessAfterInitialization方法
12.存在Spring容器里的Bean開始支持整個應用程式的運行
13.退出Web應用程式
14.關閉Spring容器
15.呼叫destroy方法銷毀Bean
可以看到Bean的生命周期從開始到結束總共經歷十五個階段,每個階段都有每個階段該做的事,現在,讓我們以庖丁解牛的手法剖開各個階段,瞧瞧里頭具體是怎樣的,以及怎樣寫些代碼參與進去,做些我們想做的事,
階段一:運行Web應用程式
這是事情的開端,在此階段,Web容器將會加載和初始化Web應用程式,使之運行起來,
階段二:創建Spring容器
Web容器初始化Web應用程式的時候,Web應用程式將會根據部署描述檔案提供的資訊創建兩個Spring容器:一個是根應用背景關系;一個是Servlet應用背景關系,每個容器都有自己創建和管理著的Bean,Bean的生命周期是與Bean所在的容器關聯的,
階段三:加載組態檔生成Bean的定義
Web應用程式創建Spring容器的時候,Spring容器將會加載組態檔,決議組態檔,根據組態檔提供的資訊生成BeanDefinition物件,BeanDefinition物件俗稱Bean的定義,保存著關于如何創建Bean的資訊,
階段四:創建實作了BeanFactoryPostProcessor介面的Bean,呼叫postProcessBeanFactory方法
BeanFactoryPostProcessor是Spring提供的一個介面,具體如下:
1 public interface BeanFactoryPostProcessor { 2 void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 3 throws BeansException; 4 }
Spring容器加載組態檔生成Bean的定義之后,開始根據Bean的定義提供的資訊創建各種Bean,創建各種Bean之前,Spring容器會先看看哪些Bean實作了BeanFactoryPostProcessor介面,并在找到之后首先創建這種型別的Bean,直到創建完畢才會接著創建其它型別的Bean
Spring容器創建完成所有實作了BeanFactoryPostProcessor介面的Bean之后,在開始創建其它型別的Bean之前,會先呼叫那些實作了BeanFactoryPostProcessor介面的Bean的postProcessBeanFactory方法,我們可在BeanFactoryPostProcessor介面的實作里修改Bean的定義,改變Spring容器即將創建的Bean的樣子,
比如,Spring提供的PropertySourcesPlaceholderConfigurer類就實作了BeanFactoryPostProcessor介面,具有讀取屬性檔案,使用屬性檔案的值替換Bean的定義里保存著的屬性占位符,從而把屬性檔案的值作為字面量值注入Bean里的功能,我們將在介紹屬性占位符的時候詳細介紹這些內容,這里暫不詳述,
階段五:創建實作了BeanPostProcessor介面的Bean
BeanPostProcessor是Spring提供的一個介面,具體如下:
1 public interface BeanPostProcessor { 2 @Nullable 3 default Object postProcessBeforeInitialization(Object bean, String beanName) 4 throws BeansException { 5 return bean; 6 } 7 8 @Nullable 9 default Object postProcessAfterInitialization(Object bean, String beanName) 10 throws BeansException { 11 return bean; 12 } 13 }
Spring容器完成所有實作了BeanFactoryPostProcessor介面的Bean的postProcessBeanFactory方法的呼叫之后,開始檢查Bean的定義,看看哪些Bean實作了BeanPostProcessor介面,并在找到之后開始創建這些Bean,直到創建完畢才會接著創建其它型別的Bean,BeanPostProcessor介面是為了參與Bean的初始化準備的,至于怎樣參與,請往下繼續閱讀,
階段六:創建其它型別的Bean
Spring容器創建完成所有實作了BeanPostProcessor介面的Bean之后,開始通過反射技術呼叫建構式,創建既沒實作BeanFactoryPostProcessor介面,也沒實作BeanPostProcessor介面的其它型別的Bean
階段七:通過屬性注入依賴
Spring容器呼叫Bean的建構式完成Bean的創建之后,開始通過屬性注入依賴,完成Bean的裝配,
階段八:呼叫Aware介面的方法
Spring提供了很多繼承了Aware介面的介面,如果我們的Bean實作了這些介面,Spring容器就能通過回呼的方式把那些框架相關的Bean傳給我們的Bean,使我們的Bean能夠使用框架相關的Bean做些事情,常見的框架相關的Bean有BeanFactory,ApplicationContext,等等,
針對BeanFactory物件,Spring提供了BeanFactoryAware介面,具體如下:
1 public interface BeanFactoryAware extends Aware { 2 void setBeanFactory(BeanFactory beanFactory) throws BeansException; 3 }
可以看到BeanFactoryAware繼承了Aware介面,定義了 void setBeanFactory(BeanFactory beanFactory) 這樣一個接受BeanFactory型別的引數的方法,如果我們的Bean實作了BeanFactoryAware介面,Spring容器完成Bean的屬性的注入之后,就會以Spring容器里存在著的BeanFactory物件作為引數呼叫setBeanFactory方法,把BeanFactory物件交給我們的Bean,使我們的Bean能用BeanFactory物件做些事情,
針對ApplicationContext物件,Spring提供了ApplicationContextAware介面,具體如下:
1 public interface ApplicationContextAware extends Aware { 2 void setApplicationContext(ApplicationContext applicationContext) 3 throws BeansException; 4 }
可以看到ApplicationContextAware繼承了Aware介面,定義了 void setApplicationContext( ApplicationContext applicationContext) 這樣一個接受ApplicationContext型別的引數的方法,如果我們的Bean實作了ApplicationContextAware介面,Spring容器完成Bean的屬性的注入之后,就會以Spring容器里存在著的ApplicationContext物件作為引數呼叫setApplicationContext方法,把ApplicationContext物件交給我們的Bean,使我們的Bean能用ApplicationContext物件做些事情,
值得注意的是,BeanFactoryAware和ApplicationContextAware都繼承了Aware介面,Aware介面具體如下:
1 public interface Aware { 2 }
里面空落落的,一個成員也沒有,因為Aware介面主要作為父介面用于派生各種各樣的Aware介面,使我們的Bean實作這些Aware介面之后,Spring容器可把Spring框架相關的物件作為引數呼叫這些介面定義的方法,讓我們的Bean能用Spring框架相關的物件做些事情,
階段九:呼叫postProcessBeforeInitialization方法
完成所有Aware介面的方法的呼叫之后,Spring容器開始進行Bean的初始化,開始初始化Bean之前,Spring容器會先查看一下Spring容器里存不存在實作了BeanPostProcessor介面的Bean,注意,實作了BeanPostProcessor介面的Bean是在階段五的時候創建的,如果存在,則會呼叫所有實作了BeanPostProcessor介面的Bean的postProcessBeforeInitialization方法,在Bean的初始化之前做些事情,
因此,如果我們想在Bean的初始化開始之前做些事情,可以定義一些實作了BeanPostProcessor介面的類,
階段十:呼叫afterPropertiesSet方法初始化Bean
afterPropertiesSet方法是InitializingBean介面定義的一個方法,具體如下:
1 public interface InitializingBean { 2 void afterPropertiesSet() throws Exception; 3 }
Spring容器完成所有實作了BeanPostProcessor介面的Bean的postProcessBeforeInitialization方法的呼叫之后,就會開始檢查我們的Bean需不需要進行初始化,如果需要,則開始進行初始化,初始化程序從先到后是這樣的:
1.檢查Bean是否定義了帶有@PostConstruct注解的初始化方法,如果定義了,則呼叫帶有@PostConstruct注解的方法進行初始化,
2.檢查Bean是否實作了InitializingBean介面,如果實作了,則呼叫afterPropertiesSet方法進行初始化,
3.檢查XML組態檔的<bean>元素是否通過init-method屬性指定了初始化方法,如果指定了,則呼叫初始化方法進行初始化,
還有,除了可以通過<bean>元素的init-method屬性指定初始化方法之外,也可通過根元素<beans>的default-init-method屬性為所有的Bean指定一個默認的初始化方法,如果同時指定了<bean>元素的init-method屬性和根元素<beans>的default-init-method屬性,則<bean>元素的init-method屬性將會覆寫根元素<beans>的default-init-method屬性指定的初始化方法,
另外,如果采用配置類進行配置的話,則可通過@Bean注解的initMethod屬性指定初始化方法,
階段十一:呼叫postProcessAfterInitialization方法
Spring容器完成Bean的初始化之后,開始檢查Spring容器里存不存在實作了BeanPostProcessor介面的Bean,注意,實作了BeanPostProcessor介面的Bean是在階段五的時候創建的,如果存在,則會呼叫所有實作了BeanPostProcessor介面的Bean的postProcessAfterInitialization方法,在完成Bean的初始化之后做些事情,
因此,如果我們想在Bean的初始化完成之后做些事情,可以定義一些實作了BeanPostProcessor介面的類,
階段十二:存在Spring容器里的Bean開始支持整個應用程式的運行
Spring容器完成所有Bean的創建和初始化之后,開始支持整個應用程式的運行,處理著來自遠方的各種請求,
階段十三:退出Web應用程式
Web應用程式退出運行,
階段十四:關閉Spring容器
Web應用程式退出的時候,Spring容器將被關閉,
階段十五:呼叫destroy方法銷毀Bean
destroy方法是DisposableBean介面定義的一個方法,具體如下:
1 public interface DisposableBean { 2 void destroy() throws Exception; 3 }
Spring容器關閉的時候,將會檢查我們的Bean需不需要做些銷毀作業,如果需要,則開始進行銷毀,銷毀程序從先到后是這樣的:
1.檢查Bean是否定義了帶有@PreDestroy注解的銷毀方法,如果定義了,則呼叫帶有@PreDestroy注解的方法進行銷毀,
2.檢查Bean是否實作了DisposableBean介面,如果實作了,則呼叫destroy方法進行銷毀,
3.檢查XML組態檔的<bean>元素是否通過destroy-method屬性指定了銷毀方法,如果指定了,則呼叫銷毀方法進行銷毀,
還有,除了可以通過<bean>元素的destroy-method屬性指定銷毀方法之外,也可通過根元素<beans>的default-destroy-method屬性為所有的Bean指定一個默認的銷毀方法,如果同時指定了<bean>元素的destroy-method屬性和根元素<beans>的default-destroy-method屬性,則<bean>元素的destroy-method屬性將會覆寫根元素<beans>的default-destroy-method屬性指定的銷毀方法,
另外,如果采用配置類進行配置的話,則可通過@Bean注解的destroyMethod屬性指定銷毀方法,
于是,Bean的整個生命周期我們已經理清楚了,也知道如何寫些代碼參與進去,需要特別提醒的是,雖然我們可以通過實作諸如BeanFactoryPostProcessor,BeanPostProcessor這樣的介面達到參與Bean的生命周期的目的;可是,這樣卻會導致我們的Bean與Spring框架產生耦合,
回傳目錄 下載代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/401398.html
標籤:其他
