当前位置: 代码网 > it编程>编程语言>Java > Spring Bean的六种作用域详解

Spring Bean的六种作用域详解

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

在 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六种作用域的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com