Spring Bean的六種作用域詳解
在 Spring 容器中,Bean 的作用域決定了 Bean 實(shí)例的創(chuàng)建規(guī)則、生命周期和使用范圍,它會直接影響程序的性能、線程安全和內(nèi)存占用。Spring 一共定義了 6 種作用域,下面我們逐一拆解。
一、singleton(單例,默認(rèn)作用域)
核心效果
- 整個 Spring IoC 容器中,只會創(chuàng)建 1 個該 Bean 的實(shí)例,所有依賴該 Bean 的對象,拿到的都是同一個實(shí)例。
- Bean 實(shí)例的生命周期與容器綁定:容器啟動時(shí)初始化,容器關(guān)閉時(shí)銷毀。
適用場景
- 無狀態(tài)的 Bean,比如 Service、DAO、工具類、配置類等。
- 這類 Bean 不會保存線程 / 用戶的私有狀態(tài),所有請求共用同一個實(shí)例,性能開銷最低。
代碼示例
// 方式1:注解方式(默認(rèn)就是 singleton,可以省略)
@Component
@Scope("singleton")
public class UserService {
}
// 方式2:XML 配置
<bean id="userService" class="com.example.service.UserService" scope="singleton"/>二、prototype(原型 / 多例)
核心效果
- 每次從容器中獲取該 Bean 時(shí),都會創(chuàng)建一個全新的實(shí)例。
- Spring 容器不負(fù)責(zé) prototype Bean 的完整生命周期:容器只會初始化、裝配 Bean,不會在關(guān)閉時(shí)銷毀它,需要使用者自己管理銷毀。
適用場景
- 有狀態(tài)的 Bean,比如需要保存用戶私有數(shù)據(jù)的對象、多線程環(huán)境下的非線程安全對象。
- 不適合頻繁創(chuàng)建的大對象(會增加 GC 壓力),適合輕量級、需要獨(dú)立狀態(tài)的 Bean。
代碼示例
@Component
@Scope("prototype")
public class OrderInfo {
// 每個請求/線程都會拿到獨(dú)立的 OrderInfo 實(shí)例
}三、request(請求域)
核心效果
- 每次 HTTP 請求,都會創(chuàng)建一個新的 Bean 實(shí)例,同一個請求內(nèi)的所有對象拿到的都是同一個實(shí)例。
- 僅在 Spring Web 環(huán)境中有效,實(shí)例的生命周期與 HTTP 請求綁定:請求結(jié)束,Bean 就會被銷毀。
適用場景
- 存儲 HTTP 請求相關(guān)的臨時(shí)數(shù)據(jù),比如請求上下文、用戶單次請求的參數(shù)對象。
- 比如 Spring MVC 中,用于封裝請求信息的對象。
代碼示例
@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestInfo {
// 每個 HTTP 請求都會創(chuàng)建獨(dú)立實(shí)例
}注意:需要配合 proxyMode 使用,否則會出現(xiàn)依賴注入異常。
四、session(會話域)
核心效果
- 每個用戶 HTTP 會話(Session),都會創(chuàng)建一個新的 Bean 實(shí)例,同一個 Session 內(nèi)的所有請求,拿到的都是同一個實(shí)例。
- 僅在 Spring Web 環(huán)境中有效,實(shí)例的生命周期與用戶 Session 綁定:Session 超時(shí) / 銷毀,Bean 就會被銷毀。
適用場景
- 存儲用戶會話級別的狀態(tài)數(shù)據(jù),比如用戶登錄信息、購物車信息、用戶偏好設(shè)置等。
代碼示例
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {
// 每個用戶會話都會創(chuàng)建獨(dú)立實(shí)例
}五、application(應(yīng)用域)
核心效果
- 整個 Web 應(yīng)用中,只會創(chuàng)建 1 個 Bean 實(shí)例,和
singleton類似,但作用域是ServletContext級別的,比singleton范圍更廣(跨多個 Spring 容器也共享)。 - 實(shí)例的生命周期與 Web 應(yīng)用綁定:應(yīng)用啟動時(shí)初始化,應(yīng)用關(guān)閉時(shí)銷毀。
適用場景
- 存儲整個應(yīng)用級別的全局?jǐn)?shù)據(jù),比如應(yīng)用配置、全局統(tǒng)計(jì)信息、公共緩存對象。
代碼示例
@Component
@Scope(value = "application", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AppConfig {
// 整個 Web 應(yīng)用中唯一實(shí)例
}六、websocket(WebSocket 域)
核心效果
- 每個 WebSocket 會話,都會創(chuàng)建一個新的 Bean 實(shí)例,同一個 WebSocket 會話內(nèi)的消息處理,都會使用同一個實(shí)例。
- 僅在 Spring WebSocket 環(huán)境中有效,實(shí)例的生命周期與 WebSocket 會話綁定:會話關(guān)閉,Bean 就會被銷毀。
適用場景
- WebSocket 長連接場景下,需要保存會話狀態(tài)的對象,比如聊天室的用戶連接信息、會話級別的消息處理器。
代碼示例
@Component
@Scope(value = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class WebSocketSessionInfo {
// 每個 WebSocket 會話創(chuàng)建獨(dú)立實(shí)例
}作用域?qū)Ρ瓤偨Y(jié)表
| 作用域 | 實(shí)例創(chuàng)建規(guī)則 | 適用環(huán)境 | 典型場景 |
|---|---|---|---|
| singleton | 容器中僅 1 個實(shí)例 | 所有環(huán)境 | Service、DAO、工具類 |
| prototype | 每次獲取都新建實(shí)例 | 所有環(huán)境 | 有狀態(tài)的對象、非線程安全對象 |
| request | 每個 HTTP 請求 1 個實(shí)例 | Web 環(huán)境 | 請求上下文、請求臨時(shí)數(shù)據(jù) |
| session | 每個用戶 Session 1 個實(shí)例 | Web 環(huán)境 | 用戶登錄信息、購物車 |
| application | 整個 Web 應(yīng)用 1 個實(shí)例 | Web 環(huán)境 | 全局配置、應(yīng)用級緩存 |
| websocket | 每個 WebSocket 會話 1 個實(shí)例 | WebSocket 環(huán)境 | 長連接會話狀態(tài) |
一、先搞懂:Bean 作用域到底是什么?
簡單說,就是 Spring 給你創(chuàng)建的對象,是「共用一個」還是「每次都給新的」,以及能用多久。比如:
- 有的對象整個程序里大家都用同一個(比如工具類)
- 有的對象每次用都給你新的(比如購物車,每個用戶都要有自己的)
二、6 種作用域,一個一個講
1. singleton(單例,默認(rèn))
大白話:整個程序里,大家共用同一個對象
- 效果:程序啟動時(shí),Spring 就創(chuàng)建好這一個對象,之后所有人調(diào)用,拿到的都是這同一個。
- 例子:就像學(xué)校的「公共飲水機(jī)」,全校同學(xué)都用這一臺,誰來接水都用它。
- 什么時(shí)候用?沒有自己的 “私有數(shù)據(jù)”,大家用著都一樣的對象,比如 Service 業(yè)務(wù)類、DAO 數(shù)據(jù)庫操作類、工具類。
2. prototype(多例 / 原型)
大白話:每次調(diào)用,都給你一個全新的對象
- 效果:你每次從 Spring 里拿這個對象,它都會給你新造一個,和之前的都不一樣。
- 例子:就像「一次性紙杯」,每個人喝水都給你一個新的,用完就扔,不會和別人共用。
- 什么時(shí)候用?每個用戶 / 每個操作都要有自己獨(dú)立狀態(tài)的對象,比如訂單信息、購物車對象,不能和別人共用。
下面 4 種,只有做網(wǎng)頁項(xiàng)目(Web 程序)才會用到,按「用多久」來分:
3. request(請求域)
大白話:一次網(wǎng)頁請求,用一個對象
- 效果:用戶點(diǎn)一下網(wǎng)頁(發(fā)一次請求),Spring 給你造一個對象,這次請求里全程都用它;等用戶刷新頁面 / 點(diǎn)下一個鏈接,這次請求結(jié)束,這個對象就扔了,下次再給新的。
- 例子:就像「一次性紙巾」,你擦一次手就扔了,下次再拿新的。
- 什么時(shí)候用?只在這一次網(wǎng)頁請求里用的數(shù)據(jù),比如用戶這次搜索的關(guān)鍵詞、臨時(shí)請求參數(shù)。
4. session(會話域)
大白話:一個用戶的一次登錄會話,用一個對象
- 效果:用戶登錄網(wǎng)站后,從登錄到退出 / 超時(shí)這段時(shí)間,全程用同一個對象;用戶退出登錄,這個對象就銷毀了。
- 例子:就像「你自己的水杯」,你在學(xué)校一天都用這一個,放學(xué)回家就收起來,第二天再用新的(或者說,每個學(xué)生都有自己的水杯,不會共用)。
- 什么時(shí)候用?要跟著用戶登錄狀態(tài)走的數(shù)據(jù),比如用戶登錄信息、購物車內(nèi)容,用戶不退出,這些數(shù)據(jù)就一直存在。
5. application(應(yīng)用域)
大白話:整個網(wǎng)站,所有人共用同一個對象
- 效果:網(wǎng)站啟動時(shí)造好,整個網(wǎng)站運(yùn)行期間,所有用戶、所有請求都用這同一個對象,和 singleton 很像,但范圍是整個網(wǎng)站。
- 例子:就像「學(xué)校的公告欄」,全校所有同學(xué)都看這一個,公告內(nèi)容更新了所有人都能看到。
- 什么時(shí)候用?整個網(wǎng)站都要用的全局?jǐn)?shù)據(jù),比如網(wǎng)站的配置信息、全站訪問量統(tǒng)計(jì)。
6. websocket(WebSocket 域)
大白話:一次 WebSocket 連接,用一個對象
- 效果:用戶和網(wǎng)站建立 WebSocket 長連接(比如聊天室、在線客服),連接期間全程用同一個對象;連接斷開,對象就銷毀了。
- 例子:就像「你打電話時(shí)的專屬通話通道」,你和客服通話期間,這個通道只屬于你,掛電話就關(guān)了。
- 什么時(shí)候用?WebSocket 長連接場景,比如聊天室里的用戶連接信息、實(shí)時(shí)聊天的會話數(shù)據(jù)。
三、給你劃重點(diǎn)(作業(yè)要寫的核心點(diǎn))
表格
| 作用域 | 一句話總結(jié) | 關(guān)鍵特點(diǎn) |
|---|---|---|
| singleton | 全程序共用 1 個 | 默認(rèn)、無狀態(tài)對象用它 |
| prototype | 每次調(diào)用給新的 | 有狀態(tài)對象用它 |
| request | 一次請求用 1 個 | 網(wǎng)頁單次請求用 |
| session | 一個用戶會話用 1 個 | 登錄用戶的會話數(shù)據(jù) |
| application | 全網(wǎng)站共用 1 個 | 全局配置 / 統(tǒng)計(jì)數(shù)據(jù) |
| websocket | 一次 WebSocket 連接用 1 個 | 長連接場景用 |
四、舉個你能懂的對比
- 學(xué)校里:
- singleton = 全校共用的操場
- prototype = 每個同學(xué)自己的筆記本
- request = 一次性考試草稿紙
- session = 你自己的儲物柜(從開學(xué)用到放假)
- application = 學(xué)校的校史館,所有人都看這一個
- websocket = 一次視頻通話的專用線路
關(guān)鍵補(bǔ)充說明
- 線程安全問題:
singleton單例 Bean 是線程共享的,必須保證線程安全(不能保存可變的成員變量狀態(tài))。prototype/request/session等多實(shí)例 Bean,每個線程 / 請求 / 會話使用獨(dú)立實(shí)例,天生線程安全。
- 性能與內(nèi)存:
singleton實(shí)例全局復(fù)用,性能最高、內(nèi)存占用最低。- 多實(shí)例作用域會頻繁創(chuàng)建銷毀對象,會增加內(nèi)存和 GC 壓力,僅在有狀態(tài)場景下使用。
- 代理模式:
request/session/application等 Web 相關(guān)作用域,需要配合@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)使用,否則在注入 singleton Bean 時(shí)會出現(xiàn)依賴注入異常。
以上就是Spring Bean的六種作用域詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring Bean六種作用域的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring中的BeanFactory對象實(shí)例化工廠詳解
這篇文章主要介紹了Spring中的BeanFactory對象實(shí)例化工廠詳解,BeanFactory及其子類是Spring IOC容器中最重要的一個類,BeanFactory由類名可以看出其是一個Bean工廠類,其實(shí)它確實(shí)是一個Bean工廠類,完成Bean的初始化操作,需要的朋友可以參考下2023-12-12
解決fastjson從1.1.41升級到1.2.28后報(bào)錯問題詳解
這篇文章主要介紹了解決fastjson從1.1.41升級到1.2.28后報(bào)錯問題詳解,需要的朋友可以參考下2020-02-02
使用CXF和Jersey框架來進(jìn)行Java的WebService編程
這篇文章主要介紹了使用CXF和Jersey框架來進(jìn)行Java的WebService編程,Web service是一個平臺獨(dú)立的低耦合的自包含的基于可編程的web的應(yīng)用程序,需要的朋友可以參考下2015-12-12
永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說明
這篇文章主要為大家介紹了永中文檔在線轉(zhuǎn)換服務(wù)Swagger調(diào)用說明,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
java去除圖片水印的四種方法實(shí)現(xiàn)與對比
這篇文章將從簡單到復(fù)雜,為大家詳細(xì)介紹幾種常見的 Java 去水印方法、適用的場景以及需要注意的事項(xiàng),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下2025-08-08
java使用@Transactional時(shí)常犯的N種錯誤
@Transactional是我們在用Spring時(shí)候幾乎逃不掉的一個注解,本文主要介紹了使用?@Transactional?時(shí)常犯的N種錯誤,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
java打成jar后,獲取resources下的文件資源問題及解決
作者在寫代碼時(shí)遇到一個問題:在將項(xiàng)目打包成jar包后,無法通過常規(guī)方式獲取resources文件夾下的資源,通過分析原因,作者找到了一種新的解決方案,即通過類加載器獲取jar包內(nèi)的資源,此方式返回后的資源以文件流的形式返回,作者將其轉(zhuǎn)換為了byte[]的形式使用2026-05-05
Spring使用AspectJ注解和XML配置實(shí)現(xiàn)AOP
這篇文章主要介紹了Spring使用AspectJ注解和XML配置實(shí)現(xiàn)AOP的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
使用spring.profiles.active來分區(qū)配置的方法示例
這篇文章主要介紹了使用spring.profiles.active來分區(qū)配置的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-01-01

