在软件开发(特别是Spring框架)中,singleton
、prototype
和 request
是三种常见的 Bean 作用域(Scope),它们决定了对象的生命周期和创建方式。以下是它们的核心区别:
1. Singleton(单例)
- 定义:整个应用中只有一个实例,所有请求共享同一个对象。
- 特点:
- 默认作用域(Spring 中不指定时默认是单例)。
- 实例在容器启动时创建(或首次请求时),直到容器销毁。
- 适用于无状态的 Bean(如工具类、服务层)。
- 示例:
@Service // 默认是单例
public class UserService {
// 所有请求共享同一个 UserService 实例
}
2. Prototype(原型)
- 定义:每次请求(或依赖注入时)都创建一个新实例。
- 特点:
- 适用于有状态的 Bean(如需要存储用户数据的对象)。
- 实例由 Spring 创建,但销毁由调用方管理(Spring 不负责回收)。
- 示例:
@Scope("prototype")
@Component
public class ShoppingCart {
// 每次注入或调用时生成新实例
}
3. Request(请求作用域)
- 定义:每个 HTTP 请求创建一个新实例,请求结束后销毁。
- 特点:
- 仅适用于 Web 应用(如 Spring MVC)。
- 适用于需要隔离请求数据的场景(如用户会话信息)。
- 示例:
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class UserSession {
// 每个 HTTP 请求有自己的 UserSession 实例
}
对比表格
作用域 | 实例数量 | 生命周期 | 适用场景 |
Singleton | 整个应用一个实例 | 容器启动到容器销毁 | 无状态服务(如 Service、DAO) |
Prototype | 每次请求新实例 | 由调用方管理 | 有状态对象(如 ShoppingCart) |
Request | 每个 HTTP 请求一个 | 请求开始到请求结束 | Web 请求数据(如表单提交) |
关键区别
- 线程安全性:
Singleton
需确保线程安全(避免共享变量)。Prototype
和Request
天然隔离,无需考虑线程安全。
- 性能:
Singleton
性能最优(无需重复创建)。Prototype
和Request
每次创建新实例,开销较大。
- 适用场景:
- 无状态服务用
Singleton
,有状态对象用Prototype
或Request
。
其他作用域(补充)
- Session:每个用户会话一个实例(如用户登录信息)。
- Application:整个 Web 应用一个实例(类似 Singleton,但用于 ServletContext)。
- WebSocket:每个 WebSocket 会话一个实例。