Spring 生命周期與作用范圍
1. 前言
? 上一節(jié),我們多學(xué)習(xí)了一種初始化 Spring 容器的方式,那么不管是何種初始化容器的方式,目的都是對容器中的 bean 實(shí)例做管理的。
本節(jié)我們就學(xué)習(xí) Spring 的容器如何管理對象的實(shí)例的。主要在于兩個方向:
- 對象的生命周期
- 對象的作用范圍
2. 對象的生命周期
2.1. 生命周期的概念
? 生命周期,通俗的理解就是從出生到死亡的過程,那么對于對象而言,就是實(shí)例在 Spring 容器中創(chuàng)建到銷毀的過程。
2.2 生命周期流程概要
簡單地來說,一個 Bean 的生命周期分為四個階段:
(1) 實(shí)例化(Instantiation)
(2) 屬性設(shè)置(populate)
(3) 初始化(Initialization)
(4) 銷毀(Destruction)
流程圖如下:
Spring 中 bean 的實(shí)例化過程:
Bean 實(shí)例生命周期的執(zhí)行過程如下:
-
Spring 對 bean 進(jìn)行實(shí)例化,默認(rèn) bean 是單例;
-
Spring 對 bean 進(jìn)行依賴注入;
-
如果 bean 實(shí)現(xiàn)了
BeanNameAware
接口,Spring 將 bean 的 id 傳給setBeanName()
方法; -
如果 bean 實(shí)現(xiàn)了
BeanFactoryAware
接口,Spring 將調(diào)用setBeanFactory
方法,將 BeanFactory 實(shí)例傳進(jìn)來; -
如果 bean 實(shí)現(xiàn)了
ApplicationContextAware
接口,它的setApplicationContext()
方法將被調(diào)用,將應(yīng)用上下文的引用傳入到 bean 中; -
如果 bean 實(shí)現(xiàn)了
BeanPostProcessor
接口,它的postProcessBeforeInitialization
方法將被調(diào)用; -
如果 bean 實(shí)現(xiàn)了
InitializingBean
接口,Spring 將調(diào)用它的afterPropertiesSet
接口方法,類似地如果 bean 使用了 init-method 屬性聲明了初始化方法,該方法也會被調(diào)用; -
如果 bean 實(shí)現(xiàn)了
BeanPostProcessor
接口,它的postProcessAfterInitialization
接口方法將被調(diào)用; -
此時 bean 已經(jīng)準(zhǔn)備就緒,可以被應(yīng)用程序使用了,他們將一直駐留在應(yīng)用上下文中,直到該應(yīng)用上下文被銷毀;
-
若 bean 實(shí)現(xiàn)了
DisposableBean
接口,Spring 將調(diào)用它的distroy()
接口方法。同樣地,如果 bean 使用了 destroy-method 屬性聲明了銷毀方法,則該方法被調(diào)用;
3. 對象的作用范圍
3.1 介紹
作用范圍四個字很好理解,其實(shí)就是對象起作用的范圍在哪,那么到底有哪些作用范圍呢?
3.2 作用范圍舉例
singleton — 單例模式
prototype — 原型模式
request — 請求范圍
session — 會話范圍
application — 應(yīng)用范圍
3.3 作用范圍詳解
單例模式
單例大家都不陌生,Java 基礎(chǔ)我們學(xué)過如何創(chuàng)建單例,而在 Spring 的容器中,bean 的作用范圍如果是 singleton,那么表示容器中僅管理一個共享實(shí)例,該單個實(shí)例存儲在 Spring 容器的緩存 map 集合中,所有的對象對于該實(shí)例的引用,都是從緩存的 map 中返回該對象的實(shí)例。
結(jié)構(gòu)圖如下:
圖片解釋:可以看到左側(cè)的三個,是通過 bean 標(biāo)簽實(shí)例化的類,而在每個類中都有個 property 引入 accountDao 的依賴,右側(cè)表示在內(nèi)存中僅存在一個 dao 的實(shí)例,
這也是默認(rèn)的實(shí)例模式 —— 單例模式。
原型模式
原型模式 聽起來比較模糊,解釋的意思就是 —— 如果 bean 的作用范圍如果是 prototype,那么表示 Spring 容器針對當(dāng)前對象獲取實(shí)例的時候,每次都會重新 new 一個對象,返回給調(diào)用者。
結(jié)構(gòu)圖如下:
圖片解釋:可以看到左側(cè)的三個,是通過 bean 標(biāo)簽實(shí)例化的類,在每個類中都有個 property 引入 accountDao 的依賴。
右側(cè)存在一個 dao 的 bean 標(biāo)簽配置。而在配置的屬性中,有一個 scope =prototype ,即是原型模式的作用范圍。 每個類中已引入的依賴,Spring 的容器都是通過 class 重新 new 一個實(shí)例分別返回給調(diào)用者。
其余模式
request
,session
,application
,等等作用范圍工作使用中并不常見,這里不做描述。大家可自行查詢資料。
4. 小結(jié)
Spring 的容器中初始化的實(shí)例,可以存在多種作用范圍,而最常用的就是 默認(rèn)的單例模式,至于 prototype 原型也有使用場景。
那么到底是單例模式,還是原型模式都是根據(jù)實(shí)際需求來決定,如果使用的實(shí)例中存在多種共享屬性,又要求數(shù)據(jù)狀態(tài)不被改變,
那么就必須是原型 prototype 模式,否則使用單例更好。