request作用域Bean每次HTTP请求创建新实例,请求结束即销毁;session作用域Bean每个用户会话维持一个实例,随session失效而销毁,二者均需WebApplicationContext支持且有特定声明与使用约束。

在 Spring Web 环境中,request 和 session 是两种常用的非单例作用域(scope),用于控制 Bean 的生命周期与可见范围。它们不是全局共享的,而是绑定到 HTTP 请求或用户会话,适合存放临时、上下文相关的数据。
request 作用域:每次请求创建一个新实例
request 作用域的 Bean 在一次完整的 HTTP 请求处理周期内有效,请求结束即销毁。适用于需要在控制器、服务、过滤器之间传递本次请求专属数据的场景,比如表单参数封装对象、请求级缓存标记等。
- 声明方式:在 Bean 定义上添加
@Scope("request"),并确保类被@Component或配置为@Bean(需在 WebApplicationContext 中) - 必须配合
WebApplicationContext使用(如使用AnnotationConfigServletWebServerApplicationContext或标准 Servlet 容器集成),否则会抛出IllegalStateException - 在 Controller 中直接注入 request-scoped Bean 是安全的,Spring 会通过代理(CGLIB 或 JDK 动态代理)实现延迟解析,避免早期初始化失败
- 示例:
@Component<br>@Scope("request")<br>public class RequestContext {<br> private final String traceId = UUID.randomUUID().toString();<br> public String getTraceId() { return traceId; }<br>}
每次请求访问该 Bean,都会拿到不同的 traceId 实例
session 作用域:每个用户会话维持一个实例
session 作用域的 Bean 绑定到 HttpSession 生命周期,在用户首次创建 session 后生成,随 session 失效(超时、手动 invalidate() 或容器重启)而销毁。适用于用户登录态、购物车、多步表单中间状态等跨请求但限于单用户的场景。
- 声明方式:使用
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS);proxyMode必须显式指定(通常用TARGET_CLASS),否则注入到 singleton Bean 时会报错 - 底层依赖容器的
HttpSession,因此要求应用部署在支持 Servlet 规范的环境(如 Tomcat、Jetty),且用户已触发 session 创建(如调用request.getSession()或启用spring.session.store-type) - 注意线程安全性:session-scoped Bean 默认是非线程安全的,多个并发请求操作同一 session Bean 的可变字段时需自行同步(如用
synchronized或Atomic类型) - 示例:
@Component<br>@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)<br>public class ShoppingCart {<br> private final List<Item> items = new ArrayList<>();<br> public void addItem(Item item) { items.add(item); }<br>}
不同浏览器标签页(同 session)共享同一个 ShoppingCart 实例
常见问题与注意事项
-
不能在普通 Java main 方法或单元测试中直接使用:request/session 依赖 Servlet 容器上下文,需用
@WebMvcTest、@SpringBootTest(webEnvironment = RANDOM_PORT)或模拟MockHttpServletRequest/MockHttpSession -
序列化要求:session-scoped Bean 及其所有字段必须可序列化(实现
Serializable),否则在 session 集群或持久化时可能失败 -
与 Spring Session 集成更灵活:若使用 Redis 或 JDBC 存储 session(通过
spring-session-data-redis),session Bean 仍按原逻辑工作,只是底层存储透明切换 - 避免滥用大对象:长时间存活的 session Bean 若持有大量数据或外部资源(如未关闭的流、监听器),易引发内存泄漏或连接耗尽
替代方案建议
现代 Spring Web 应用中,部分传统 session 场景正被更轻量的方式替代:
立即学习“Java免费学习笔记(深入)”;
- 认证/授权推荐用
SecurityContext+ JWT 或 OAuth2,而非将用户信息全塞进 session Bean - 前端状态管理(如多步骤表单)可结合 RESTful API + 前端本地存储(localStorage/sessionStorage),后端只校验和落库,减少服务端 session 依赖
- 短生命周期上下文数据优先考虑 request scope 或方法参数(如
@RequestAttribute、@ModelAttribute),比 session 更清晰可控


















