Spring Bean的六种作用域详解

 更新时间:2026年04月21日 09:16:41   作者:老神在在001  
文章介绍了Spring框架中6种Bean作用域类型,包括singleton(单例,默认),prototype(原型)request(请求域)session(会话域)application(应用域)和websocket(WebSocket域),每种解释了作用域的核心效果、适用场景和代码示例,需要的朋友可以参考下

在 Spring 容器中,Bean 的作用域决定了 Bean 实例的创建规则、生命周期和使用范围,它会直接影响程序的性能、线程安全和内存占用。Spring 一共定义了 6 种作用域,下面我们逐一拆解。

一、singleton(单例,默认作用域)

核心效果

  • 整个 Spring IoC 容器中,只会创建 1 个该 Bean 的实例,所有依赖该 Bean 的对象,拿到的都是同一个实例。
  • Bean 实例的生命周期与容器绑定:容器启动时初始化,容器关闭时销毁。

适用场景

  • 无状态的 Bean,比如 Service、DAO、工具类、配置类等。
  • 这类 Bean 不会保存线程 / 用户的私有状态,所有请求共用同一个实例,性能开销最低。

代码示例

// 方式1:注解方式(默认就是 singleton,可以省略)
@Component
@Scope("singleton")
public class UserService {
}
// 方式2:XML 配置
<bean id="userService" class="com.example.service.UserService" scope="singleton"/>

二、prototype(原型 / 多例)

核心效果

  • 每次从容器中获取该 Bean 时,都会创建一个全新的实例
  • Spring 容器不负责 prototype Bean 的完整生命周期:容器只会初始化、装配 Bean,不会在关闭时销毁它,需要使用者自己管理销毁。

适用场景

  • 有状态的 Bean,比如需要保存用户私有数据的对象、多线程环境下的非线程安全对象。
  • 不适合频繁创建的大对象(会增加 GC 压力),适合轻量级、需要独立状态的 Bean。

代码示例

@Component
@Scope("prototype")
public class OrderInfo {
    // 每个请求/线程都会拿到独立的 OrderInfo 实例
}

三、request(请求域)

核心效果

  • 每次 HTTP 请求,都会创建一个新的 Bean 实例,同一个请求内的所有对象拿到的都是同一个实例。
  • 仅在 Spring Web 环境中有效,实例的生命周期与 HTTP 请求绑定:请求结束,Bean 就会被销毁。

适用场景

  • 存储 HTTP 请求相关的临时数据,比如请求上下文、用户单次请求的参数对象。
  • 比如 Spring MVC 中,用于封装请求信息的对象。

代码示例

@Component
@Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestInfo {
    // 每个 HTTP 请求都会创建独立实例
}

注意:需要配合 proxyMode 使用,否则会出现依赖注入异常。

四、session(会话域)

核心效果

  • 每个用户 HTTP 会话(Session),都会创建一个新的 Bean 实例,同一个 Session 内的所有请求,拿到的都是同一个实例。
  • 仅在 Spring Web 环境中有效,实例的生命周期与用户 Session 绑定:Session 超时 / 销毁,Bean 就会被销毁。

适用场景

  • 存储用户会话级别的状态数据,比如用户登录信息、购物车信息、用户偏好设置等。

代码示例

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {
    // 每个用户会话都会创建独立实例
}

五、application(应用域)

核心效果

  • 整个 Web 应用中,只会创建 1 个 Bean 实例,和 singleton 类似,但作用域是 ServletContext 级别的,比 singleton 范围更广(跨多个 Spring 容器也共享)。
  • 实例的生命周期与 Web 应用绑定:应用启动时初始化,应用关闭时销毁。

适用场景

  • 存储整个应用级别的全局数据,比如应用配置、全局统计信息、公共缓存对象。

代码示例

@Component
@Scope(value = "application", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class AppConfig {
    // 整个 Web 应用中唯一实例
}

六、websocket(WebSocket 域)

核心效果

  • 每个 WebSocket 会话,都会创建一个新的 Bean 实例,同一个 WebSocket 会话内的消息处理,都会使用同一个实例。
  • 仅在 Spring WebSocket 环境中有效,实例的生命周期与 WebSocket 会话绑定:会话关闭,Bean 就会被销毁。

适用场景

  • WebSocket 长连接场景下,需要保存会话状态的对象,比如聊天室的用户连接信息、会话级别的消息处理器。

代码示例

@Component
@Scope(value = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class WebSocketSessionInfo {
    // 每个 WebSocket 会话创建独立实例
}

作用域对比总结表

作用域实例创建规则适用环境典型场景
singleton容器中仅 1 个实例所有环境Service、DAO、工具类
prototype每次获取都新建实例所有环境有状态的对象、非线程安全对象
request每个 HTTP 请求 1 个实例Web 环境请求上下文、请求临时数据
session每个用户 Session 1 个实例Web 环境用户登录信息、购物车
application整个 Web 应用 1 个实例Web 环境全局配置、应用级缓存
websocket每个 WebSocket 会话 1 个实例WebSocket 环境长连接会话状态

一、先搞懂:Bean 作用域到底是什么?

简单说,就是 Spring 给你创建的对象,是「共用一个」还是「每次都给新的」,以及能用多久。比如:

  • 有的对象整个程序里大家都用同一个(比如工具类)
  • 有的对象每次用都给你新的(比如购物车,每个用户都要有自己的)

二、6 种作用域,一个一个讲

1. singleton(单例,默认)

大白话:整个程序里,大家共用同一个对象

  • 效果:程序启动时,Spring 就创建好这一个对象,之后所有人调用,拿到的都是这同一个。
  • 例子:就像学校的「公共饮水机」,全校同学都用这一台,谁来接水都用它。
  • 什么时候用?没有自己的 “私有数据”,大家用着都一样的对象,比如 Service 业务类、DAO 数据库操作类、工具类。

2. prototype(多例 / 原型)

大白话:每次调用,都给你一个全新的对象

  • 效果:你每次从 Spring 里拿这个对象,它都会给你新造一个,和之前的都不一样。
  • 例子:就像「一次性纸杯」,每个人喝水都给你一个新的,用完就扔,不会和别人共用。
  • 什么时候用?每个用户 / 每个操作都要有自己独立状态的对象,比如订单信息、购物车对象,不能和别人共用。

下面 4 种,只有做网页项目(Web 程序)才会用到,按「用多久」来分:

3. request(请求域)

大白话:一次网页请求,用一个对象

  • 效果:用户点一下网页(发一次请求),Spring 给你造一个对象,这次请求里全程都用它;等用户刷新页面 / 点下一个链接,这次请求结束,这个对象就扔了,下次再给新的。
  • 例子:就像「一次性纸巾」,你擦一次手就扔了,下次再拿新的。
  • 什么时候用?只在这一次网页请求里用的数据,比如用户这次搜索的关键词、临时请求参数。

4. session(会话域)

大白话:一个用户的一次登录会话,用一个对象

  • 效果:用户登录网站后,从登录到退出 / 超时这段时间,全程用同一个对象;用户退出登录,这个对象就销毁了。
  • 例子:就像「你自己的水杯」,你在学校一天都用这一个,放学回家就收起来,第二天再用新的(或者说,每个学生都有自己的水杯,不会共用)。
  • 什么时候用?要跟着用户登录状态走的数据,比如用户登录信息、购物车内容,用户不退出,这些数据就一直存在。

5. application(应用域)

大白话:整个网站,所有人共用同一个对象

  • 效果:网站启动时造好,整个网站运行期间,所有用户、所有请求都用这同一个对象,和 singleton 很像,但范围是整个网站。
  • 例子:就像「学校的公告栏」,全校所有同学都看这一个,公告内容更新了所有人都能看到。
  • 什么时候用?整个网站都要用的全局数据,比如网站的配置信息、全站访问量统计。

6. websocket(WebSocket 域)

大白话:一次 WebSocket 连接,用一个对象

  • 效果:用户和网站建立 WebSocket 长连接(比如聊天室、在线客服),连接期间全程用同一个对象;连接断开,对象就销毁了。
  • 例子:就像「你打电话时的专属通话通道」,你和客服通话期间,这个通道只属于你,挂电话就关了。
  • 什么时候用?WebSocket 长连接场景,比如聊天室里的用户连接信息、实时聊天的会话数据。

三、给你划重点(作业要写的核心点)

表格

作用域一句话总结关键特点
singleton全程序共用 1 个默认、无状态对象用它
prototype每次调用给新的有状态对象用它
request一次请求用 1 个网页单次请求用
session一个用户会话用 1 个登录用户的会话数据
application全网站共用 1 个全局配置 / 统计数据
websocket一次 WebSocket 连接用 1 个长连接场景用

四、举个你能懂的对比

  • 学校里:
    • singleton = 全校共用的操场
    • prototype = 每个同学自己的笔记本
    • request = 一次性考试草稿纸
    • session = 你自己的储物柜(从开学用到放假)
    • application = 学校的校史馆,所有人都看这一个
    • websocket = 一次视频通话的专用线路

关键补充说明

  1. 线程安全问题
    • singleton 单例 Bean 是线程共享的,必须保证线程安全(不能保存可变的成员变量状态)。
    • prototype/request/session 等多实例 Bean,每个线程 / 请求 / 会话使用独立实例,天生线程安全。
  2. 性能与内存
    • singleton 实例全局复用,性能最高、内存占用最低。
    • 多实例作用域会频繁创建销毁对象,会增加内存和 GC 压力,仅在有状态场景下使用。
  3. 代理模式
    • request/session/application 等 Web 相关作用域,需要配合 @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) 使用,否则在注入 singleton Bean 时会出现依赖注入异常。

以上就是Spring Bean的六种作用域详解的详细内容,更多关于Spring Bean六种作用域的资料请关注脚本之家其它相关文章!

相关文章

  • Java单例模式实现的几种方式

    Java单例模式实现的几种方式

    这篇文章主要介绍了Java单例模式实现的几种方式的相关资料,需要的朋友可以参考下
    2016-09-09
  • Springboot整合Mybatis传值的常用方式总结

    Springboot整合Mybatis传值的常用方式总结

    今天给大家带来的是关于Springboot的相关知识,文章围绕着Springboot整合Mybatis传值的常用方式展开,文中有非常详细的介绍及代码示例,需要的朋友可以参考下
    2021-06-06
  • 完美解决java读取大文件内存溢出的问题

    完美解决java读取大文件内存溢出的问题

    下面小编就为大家带来一篇完美解决java读取大文件内存溢出的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • java 分割csv数据的实例详解

    java 分割csv数据的实例详解

    这篇文章主要介绍了java 分割csv数据的实例详解的相关资料,这里提供了简单实例,需要的朋友可以参考下
    2017-07-07
  • java 实现读取clob

    java 实现读取clob

    这篇文章主要介绍了java 如何实现读取clob,帮助大家更好的理解和使用Java,感兴趣的朋友可以了解下
    2020-10-10
  • Java语言实现反转链表代码示例

    Java语言实现反转链表代码示例

    这篇文章主要介绍了Java语言实现反转链表代码示例,小编觉得挺不错的,这里分享给大家,供需要的朋友参考。
    2017-10-10
  • java中文传值乱码问题的解决方法

    java中文传值乱码问题的解决方法

    这篇文章主要为大家详细介绍了java中文传值乱码问题的解决方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-11-11
  • Spring Boot使用MyBatis进行两个表的关联

    Spring Boot使用MyBatis进行两个表的关联

    本文主要介绍了Spring Boot使用MyBatis进行两个表的关联,通过实例演示了如何使用MyBatis的XML映射文件和注解实现关联操作,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • Java File类的概述及常用方法使用详解

    Java File类的概述及常用方法使用详解

    Java File类的功能非常强大,下面这篇文章主要给大家介绍了关于Java中File类的概述及常用方法使用,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • mybatis时间范围查询代码示例

    mybatis时间范围查询代码示例

    这篇文章主要给大家介绍了关于mybatis时间范围查询的相关资料,在项⽬中避免不了要⽤到时间范围查询,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-08-08

最新评论