0

0

Spring中Bean的作用域(Scope)有哪些?

夢幻星辰

夢幻星辰

发布时间:2025-09-04 17:19:01

|

576人浏览过

|

来源于php中文网

原创

spring中bean的作用域主要有singleton、prototype、request、session、application和websocket。singleton是默认作用域,容器中仅存在一个共享实例,适用于无状态的service或dao组件,能提升性能但需注意线程安全;prototype每次请求都会创建新实例,适合有状态或非线程安全的对象,但需自行管理资源释放;request作用域为每个http请求创建独立bean实例,用于处理请求级数据;session作用域确保每个用户会话拥有一个bean实例,常用于购物车或登录状态;application作用域在整个web应用生命周期内创建唯一实例,供所有用户共享,适合全局配置;websocket作用域用于websocket会话中维护状态。spring默认使用singleton,因其高效复用、减少开销,符合无状态服务设计原则,体现“约定优于配置”理念。prototype适用于有状态、非线程安全或短生命周期对象,但带来性能损耗和资源管理负担。在web应用中,request、session、application的区别在于生命周期和可见范围:request对应单次请求,session对应用户会话,application对应整个应用上下文,选择应基于数据的共享需求和生命周期。

spring中bean的作用域(scope)有哪些?

Spring中Bean的作用域(Scope)主要有几种:

singleton
(单例)、
prototype
(原型)、
request
(请求)、
session
(会话)以及
application
(应用)。理解它们对于我们管理Spring容器中的对象生命周期至关重要,也直接影响到应用的性能和行为。

我们来逐一看看这些作用域的含义和它们在不同场景下的应用。

  • Singleton (单例) 这是Spring容器默认的作用域。这意味着对于容器中的一个Bean定义,Spring只会创建一个唯一的实例。所有对该Bean的引用都将指向这个相同的实例。这很适合无状态的服务层Bean,比如Service、DAO等,因为它们通常不持有特定的用户数据,可以被多个请求共享。我个人觉得,这也是Spring设计哲学的一个体现,即通过复用对象来节省资源,提高性能。但话说回来,如果你的Bean有状态,且这个状态是多线程共享的,那就要特别小心线程安全问题了。

  • Prototype (原型) 与单例相反,每次从容器中请求

    prototype
    作用域的Bean时,Spring都会创建一个新的实例。这对于有状态的Bean非常有用,比如一个代表业务流程的WorkFlow对象,或者每次都需要全新数据的配置对象。我记得有一次,我们团队在处理一个批处理任务时,不小心把一个会话级别的统计Bean设成了单例,结果不同批次的数据互相污染,排查了半天才发现是作用域搞错了。从那以后,我对
    prototype
    的理解就深刻多了。

  • Request (请求) 这个作用域只在Web应用中有效。它意味着对于每个HTTP请求,Spring容器会创建一个新的Bean实例。请求结束时,该Bean实例也会被销毁。这对于那些需要在单个HTTP请求生命周期内维护状态的Bean非常有用,比如一个存储当前请求用户信息的Bean。想象一下,一个用户登录后,其请求上下文信息就可以通过

    request
    作用域的Bean来传递,而不会与另一个用户的请求混淆。

  • Session (会话) 同样是Web应用专属,

    session
    作用域的Bean在每个HTTP Session中只创建一个实例。这意味着只要用户会话存在,这个Bean就一直存在。它非常适合存储用户登录状态、购物车信息等会话级别的数据。我常常用它来存储一些用户偏好设置,这样用户在同一个会话中访问不同页面时,这些设置都能保持一致。

  • Application (应用) 这个作用域的Bean在整个Web应用生命周期内只创建一个实例,并且这个实例在所有Servlet Context中都是可见的。它类似于Web应用中的单例,但作用范围更广,通常用于存储一些全局的配置信息、统计数据或者共享资源。例如,一个全局的计数器,或者一个加载了应用启动时所需资源的Bean,就可以设置为

    application
    作用域。

  • WebSocket (WebSocket) 虽然不是最常见的,但在Spring 4.0及更高版本中,如果你开发WebSocket应用,还可以使用

    websocket
    作用域。它为每个WebSocket会话创建一个Bean实例。这对于在WebSocket连接生命周期内维护状态的Bean很有用。

为什么Spring默认选择单例(Singleton)作为Bean作用域?

Spring将

singleton
作为默认作用域,这背后有几个非常实际且深思熟虑的原因。首先,也是最核心的一点,是为了资源效率。创建对象,尤其是那些复杂、依赖注入多的对象,是需要消耗CPU和内存的。如果每次需要都创建一个新实例,系统开销会非常大。通过单例,Spring容器在启动时或首次请求时创建一次,之后就复用这个实例,极大地减少了对象创建和垃圾回收的频率,从而提升了应用的整体性能和响应速度。

其次,无状态服务的设计理念。在企业级应用中,很多组件,比如Service层、DAO层,它们的核心职责是执行业务逻辑或数据操作,本身并不需要持有特定的用户状态。它们可以被多个客户端或线程安全地共享。将这些组件设计为单例,完美契合了这种无状态服务的设计模式,避免了不必要的对象膨胀。

再者,简化管理和配置。作为默认值,单例减少了开发者在配置Bean时的心智负担。大多数情况下,我们确实需要单例行为,如果每次都要显式指定,反而会增加代码的冗余。Spring的这种默认选择,无疑是基于“约定优于配置”原则的一个体现。

Beyond商城 2008修改版
Beyond商城 2008修改版

感谢广大歌迷长期以来对网站的支持和帮助,很多朋友曾经问我要过这个商城程序,当时由于工作比较忙,一直没空整理,现在好啦,已全部整理好了,在这里提供给有需要的朋友,没有任何功能限制,完全可以使用的,只是有些商品的广告需自己修改一下,后台没有办法修改,需要有HTML基础才可以修改,另外,哪位朋友在使用的时候,发现了BUG请与我们联系,大家共同改进,谢谢!后台管理地址:http://你的域名/admin/

下载

当然,这并非没有代价。单例Bean必须是线程安全的,或者至少是无状态的。如果一个单例Bean内部维护了可变状态,并且这个状态会被多个线程同时访问和修改,那么就非常容易出现并发问题,这在实际开发中是需要特别注意的。我记得有一次,我们团队的一个单例缓存服务因为没有正确处理并发写入,导致数据不一致,排查了很久才定位到问题。所以,虽然单例是默认且高效的,但绝不能忽视其潜在的线程安全风险。

何时应该考虑使用原型(Prototype)作用域?

使用

prototype
作用域,就像是告诉Spring:“每次我需要这个Bean时,请给我一个全新的、干净的副本。” 这种需求通常出现在以下几种情况:

  • 有状态的业务对象:当你的Bean需要维护一个特定于操作或用户会话的状态时,
    prototype
    是理想选择。比如,一个表示订单的
    Order
    对象,每次创建新订单时都需要一个全新的实例来填充数据;或者一个工作流引擎中的
    WorkflowContext
    对象,每次执行一个工作流实例都需要独立的上下文。如果这些Bean是单例的,那么不同订单或工作流实例的数据就会混淆。
  • 非线程安全的对象:如果一个类本身不是线程安全的,并且你无法或者不希望对其进行同步处理,那么将其定义为
    prototype
    作用域是一个简单有效的解决方案。这样,每个线程或每次使用都能获得一个独立的实例,避免了共享状态带来的并发问题。
  • 短生命周期的辅助对象:有些对象只在某个特定操作的短时间内有效,操作结束后就可以被丢弃。例如,一个临时的报表生成器、一个一次性数据处理器。这些对象通常不需要被容器长期管理,每次创建新的实例更符合其生命周期。
  • Bean内部有可变依赖:如果一个Bean依赖于其他
    prototype
    作用域的Bean,或者它内部的某些成员变量需要在每次使用时都初始化为全新状态,那么这个Bean本身也可能需要被定义为
    prototype

然而,使用

prototype
也有其缺点。最明显的就是性能开销。每次请求都会触发Bean的实例化、依赖注入以及可能的初始化方法调用,这会增加CPU和内存的消耗。Spring容器不会管理
prototype
Bean的完整生命周期,特别是销毁回调(
destroy
方法)不会被自动调用。这意味着如果你在
prototype
Bean中持有了一些需要手动释放的资源,比如数据库连接、文件句柄,那么你需要自己负责在不再使用时进行清理。这一点我个人觉得是开发者在使用
prototype
时最容易忽视的坑,往往导致资源泄露。所以,选择
prototype
时,一定要权衡其带来的便利性和潜在的资源管理责任。

Web应用中常用的作用域(Request, Session, Application)有什么区别?

在Web应用环境中,

request
session
application
这三种作用域为我们提供了更细粒度的Bean生命周期管理,它们各自服务于不同的场景:

  • Request 作用域:一次HTTP请求的生命周期

    request
    作用域的Bean的生命周期与单个HTTP请求完全同步。当一个HTTP请求进入时,Spring会为这个请求创建一个新的Bean实例。请求处理完毕(响应发送回客户端)后,这个Bean实例就会被销毁。 典型应用场景:存储与当前请求强相关的临时数据,比如表单提交的数据、用户在当前页面上的选择、一次查询操作的过滤条件等。例如,你可能有一个
    RequestScopedUserContext
    Bean,它在每个请求中存储当前登录用户的ID和权限信息,确保不同请求之间的数据隔离。

  • Session 作用域:一个用户会话的生命周期

    session
    作用域的Bean的生命周期与用户的HTTP Session绑定。当一个用户首次访问应用并创建会话时,Spring会为这个会话创建一个Bean实例。只要这个会话保持活跃(用户持续交互或未超时),这个Bean实例就一直存在。当会话失效(用户登出、超时)时,Bean实例随之销毁。 典型应用场景:存储与特定用户会话相关的持久性数据,如购物车内容、用户登录状态、用户偏好设置、多步骤表单的中间数据等。一个
    ShoppingCart
    Bean就是一个典型的
    session
    作用域的例子,它记录了用户在整个购物过程中的选购商品。

  • Application 作用域:整个Web应用的生命周期

    application
    作用域的Bean的生命周期与整个Web应用(Servlet Context)的生命周期一致。在Web应用启动时,Spring会创建这个Bean的实例,并且这个实例在整个应用运行期间都是唯一的,可以被所有用户、所有请求共享。当Web应用关闭时,Bean实例才会被销毁。 典型应用场景:存储全局的、应用级别的配置信息、统计数据、缓存对象、或者需要在应用启动时加载一次的资源。例如,一个
    GlobalConfig
    Bean可能存储了数据库连接池配置、系统常量;一个
    AccessCounter
    Bean可以统计整个应用的访问量。它本质上是Web环境下的单例,但比普通单例的可见范围更广,直接绑定到
    ServletContext

关键区别总结: | 特性 | Request Scope | Session Scope | Application Scope | | :--- | :--- | :--- | :--- | | 生命周期 | 单个HTTP请求 | 单个HTTP会话 | 整个Web应用 | | 可见性 | 仅当前请求可见 | 仅当前会话可见 | 所有请求、所有会话可见 | | 实例数量 | 每个请求一个 | 每个会话一个 | 整个应用一个 | | 用途 | 临时请求数据 | 用户会话数据 | 全局配置、共享资源 |

选择哪种作用域,完全取决于Bean所承载的数据的生命周期和共享需求。如果数据只在一次请求中有效,用

request
;如果数据需要跟随用户会话,用
session
;如果数据是全局的、应用级别的,用
application
。我个人在设计Web应用时,会优先考虑
request
session
来隔离用户数据,而
application
则用来放置那些真正不随用户或请求变化的公共资源。这能有效避免数据混乱和潜在的并发问题。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

156

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

88

2026.01.26

servlet生命周期
servlet生命周期

Servlet生命周期是指Servlet从创建到销毁的整个过程。本专题为大家提供servlet生命周期的各类文章,大家可以免费体验。

393

2023.08.08

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1566

2023.10.24

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

334

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

776

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

97

2025.08.19

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Django 教程
Django 教程

共28课时 | 4.9万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

Sass 教程
Sass 教程

共14课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号