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

