Bean 的范圍:
范圍 | 描述 |
---|---|
singleton | (默認(rèn))將單個(gè) bean 定義范圍限定為每個(gè) Spring IoC 容器的單個(gè)對(duì)象實(shí)例周崭。 |
prototype | 將單個(gè) bean 定義范圍限定為任意數(shù)量的對(duì)象實(shí)例冤狡。 |
request | 將單個(gè) bean 定義范圍限定為單個(gè) HTTP 請(qǐng)求的生命周期。也就是說(shuō)垮兑,每個(gè) HTTP 請(qǐng)求都有自己的 bean 實(shí)例族檬,該 bean 實(shí)例是在單個(gè) bean 定義的后面創(chuàng)建的硬鞍。僅在 web-aware Spring 的上下文中有效ApplicationContext 。 |
session | 將單個(gè) bean 定義范圍限定為 HTTP 的生命周期Session 酷勺。僅在 web-aware Spring 的上下文中有效ApplicationContext 本橙。 |
application | 將單個(gè) bean 定義范圍限定為ServletContext . 僅在 web-aware Spring 的上下文中有效ApplicationContext 。 |
websocket | 將單個(gè) bean 定義范圍限定為WebSocket . 僅在 web-aware Spring 的上下文中有效ApplicationContext 脆诉。 |
單例作用域
當(dāng)您定義一個(gè) bean 定義并且它的作用域是一個(gè)單例時(shí)甚亭,Spring IoC 容器會(huì)創(chuàng)建該 bean 定義定義的對(duì)象的一個(gè)實(shí)例。該單個(gè)實(shí)例存儲(chǔ)在此類單例 bean 的緩存中库说,并且對(duì)該命名 bean 的所有后續(xù)請(qǐng)求和引用都返回緩存對(duì)象狂鞋。下圖顯示了單例范圍的工作原理:
Spring 的單例 bean 概念不同于四人組 (GoF) 模式書中定義的單例模式。GoF 單例對(duì)對(duì)象的范圍進(jìn)行了硬編碼潜的,以便每個(gè) ClassLoader 只創(chuàng)建一個(gè)特定類的一個(gè)實(shí)例骚揍。Spring 單例的范圍最好描述為每個(gè)容器和每個(gè) bean。這意味著,如果您在單個(gè) Spring 容器中為特定類定義一個(gè) bean信不,則 Spring 容器會(huì)創(chuàng)建該 bean 定義定義的類的一個(gè)且僅一個(gè)實(shí)例嘲叔。單例作用域是 Spring 中的默認(rèn)作用域。要將 bean 定義為 XML 中的單例抽活,您可以定義一個(gè) bean硫戈,如下例所示:
<bean id="accountService" class="com.something.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
原型范圍
bean 部署的非單一原型范圍導(dǎo)致每次對(duì)特定 bean 發(fā)出請(qǐng)求時(shí)都會(huì)創(chuàng)建一個(gè)新 bean 實(shí)例。也就是說(shuō)下硕,bean 被注入到另一個(gè) bean 中丁逝,或者您通過(guò)getBean()
容器上的方法調(diào)用來(lái)請(qǐng)求它。通常梭姓,您應(yīng)該對(duì)所有有狀態(tài) bean 使用原型作用域霜幼,對(duì)無(wú)狀態(tài) bean 使用單例作用域。
下圖說(shuō)明了 Spring 原型范圍:
(數(shù)據(jù)訪問(wèn)對(duì)象 (DAO) 通常不配置為原型誉尖,因?yàn)榈湫偷?DAO 不保存任何對(duì)話狀態(tài)罪既。我們更容易重用單例圖的核心。)
以下示例將 bean 定義為 XML 中的原型:
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
與其他作用域相比铡恕,Spring 不管理原型 bean 的完整生命周期琢感。容器實(shí)例化、配置和以其他方式組裝原型對(duì)象并將其交給客戶端探熔,沒(méi)有該原型實(shí)例的進(jìn)一步記錄驹针。因此,盡管在所有對(duì)象上調(diào)用初始化生命周期回調(diào)方法祭刚,而不管范圍如何牌捷,但在原型的情況下墙牌,不會(huì)調(diào)用配置的銷毀生命周期回調(diào)涡驮。客戶端代碼必須清理原型范圍內(nèi)的對(duì)象并釋放原型 bean 持有的昂貴資源喜滨。要讓 Spring 容器釋放原型作用域 bean 持有的資源捉捅,請(qǐng)嘗試使用自定義bean post-processor,它保存對(duì)需要清理的 bean 的引用虽风。
在某些方面棒口,Spring 容器在原型作用域 bean 方面的角色是 Javanew
運(yùn)算符的替代品。超過(guò)該點(diǎn)的所有生命周期管理都必須由客戶端處理辜膝。
請(qǐng)求无牵、會(huì)話、應(yīng)用程序和 WebSocket 范圍
在request
厂抖,session
茎毁,application
,和websocket
范圍只有當(dāng)你使用一個(gè)基于web的Spring在ApplicationContext
實(shí)現(xiàn)(例如 XmlWebApplicationContext
)。如果將這些作用域與常規(guī) Spring IoC 容器(例如 )一起使用ClassPathXmlApplicationContext
七蜘,IllegalStateException
則會(huì)拋出抱怨未知 bean 作用域的 谭溉。
請(qǐng)求范圍
考慮以下 bean 定義的 XML 配置:
<bean id="loginAction" class="com.something.LoginAction" scope="request"/>
Spring 容器LoginAction
通過(guò)loginAction
對(duì)每個(gè) HTTP 請(qǐng)求使用bean 定義來(lái)創(chuàng)建bean 的新實(shí)例。也就是說(shuō)橡卤, loginAction
bean 的范圍在 HTTP 請(qǐng)求級(jí)別扮念。您可以根據(jù)需要更改所創(chuàng)建實(shí)例的內(nèi)部狀態(tài),因?yàn)閺耐?code>loginActionbean 定義創(chuàng)建的其他實(shí)例看不到這些狀態(tài)更改碧库。它們是針對(duì)個(gè)人要求的柜与。當(dāng)請(qǐng)求完成處理時(shí),該請(qǐng)求范圍內(nèi)的 bean 將被丟棄嵌灰。
當(dāng)使用注解驅(qū)動(dòng)的組件或 Java 配置時(shí)旅挤,@RequestScope
注解可用于將組件分配給request
作用域。以下示例顯示了如何執(zhí)行此操作:
@RequestScope
@Component
public class LoginAction {
// ...
}
會(huì)話范圍
考慮以下 bean 定義的 XML 配置:
<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>
Spring 容器UserPreferences
通過(guò)在userPreferences
單個(gè) HTTP 的生命周期中使用bean 定義來(lái)創(chuàng)建bean 的新實(shí)例Session
伞鲫。換句話說(shuō)粘茄,userPreferences
bean 有效地限定在 HTTPSession
級(jí)別。與請(qǐng)求范圍的 bean 一樣秕脓,您可以根據(jù)需要更改所創(chuàng)建實(shí)例的內(nèi)部狀態(tài)柒瓣,因?yàn)橹榔渌?code>Session也在使用從相同userPreferences
bean 定義創(chuàng)建的實(shí)例的HTTP實(shí)例不會(huì)看到這些狀態(tài)更改,因?yàn)樗鼈兲囟ㄓ趩蝹€(gè) HTTP Session
吠架。當(dāng) HTTPSession
最終被丟棄時(shí)芙贫,作用域?yàn)樵撎囟?HTTP 的 bean Session
也將被丟棄。
當(dāng)使用注解驅(qū)動(dòng)的組件或 Java 配置時(shí)傍药,您可以使用 @SessionScope
注解將組件分配給session
作用域磺平。
@SessionScope
@Component
public class UserPreferences {
// ...
}
應(yīng)用程序范圍
考慮以下 bean 定義的 XML 配置:
<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>
Spring 容器AppPreferences
通過(guò)appPreferences
對(duì)整個(gè) Web 應(yīng)用程序使用一次 bean 定義來(lái)創(chuàng)建bean 的新實(shí)例。也就是說(shuō)拐辽, appPreferences
bean 的作用域在ServletContext
級(jí)別并存儲(chǔ)為常規(guī) ServletContext
屬性拣挪。這有點(diǎn)類似于 Spring 單例 bean,但在兩個(gè)重要方面有所不同:它是一個(gè)單例 per ServletContext
俱诸,而不是 per Spring ApplicationContext
(在任何給定的 Web 應(yīng)用程序中可能有多個(gè))菠劝,并且它實(shí)際上是公開的,因此作為一個(gè)ServletContext
屬性可見.
當(dāng)使用注解驅(qū)動(dòng)的組件或 Java 配置時(shí)睁搭,您可以使用 @ApplicationScope
注解將組件分配給application
作用域赶诊。以下示例顯示了如何執(zhí)行此操作:
@ApplicationScope
@Component
public class AppPreferences {
// ...
}
以上文檔來(lái)自Spring官方網(wǎng)站,關(guān)于 Spring-framework 文檔 Bean作用域介紹园骆。