文章目录
项目代码
https://gitee.com/he-weigang/request-and-proto-type.git
我来详细解释这两个Spring Bean作用域注解的区别,并查看项目中的相关代码示例。
Read file: src/main/java/org/example/beans/RequestScopeBean.java
Read file: src/main/java/org/example/beans/PrototypeBean.java
Read file: src/main/java/org/example/service/ScopeTestService.java
根据你项目中的代码,我来详细解释这两种Spring Bean作用域注解的区别:
主要区别
1. 作用域生命周期
@Scope("prototype")
(原型作用域):
@Component
@Scope("prototype")
public class PrototypeBean {
// 每次从容器获取时都创建新实例
}
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
(请求作用域):
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestScopeBean {
// 每个HTTP请求创建一个实例,请求结束时销毁
}
2. 创建时机和频率
- Prototype作用域:每次调用
applicationContext.getBean()
或注入时都创建新实例 - Request作用域:每个HTTP请求只创建一次,在整个请求处理过程中复用同一个实例
3. 使用环境限制
- Prototype作用域:任何Spring环境都可以使用(包括独立应用程序)
- Request作用域:只能在Web环境中使用,需要HTTP请求上下文
4. 代理模式 (proxyMode)
Request作用域必须使用代理模式:
proxyMode = ScopedProxyMode.TARGET_CLASS
这是因为:
- Request作用域Bean的生命周期比注入它的Singleton Bean短
- Spring创建一个代理对象,在运行时动态获取当前请求对应的Bean实例
- Prototype作用域不需要代理,因为每次获取都是新实例
5. 内存管理
- Prototype:Spring容器不负责销毁,需要手动管理
- Request:请求结束时自动销毁,Spring容器负责生命周期管理
实际测试对比
让我创建一个对比测试来演示区别:
Ran tool
总结对比表
特性 | @Scope("prototype") |
@Scope(value = SCOPE_REQUEST, proxyMode = TARGET_CLASS) |
---|---|---|
创建频率 | 每次获取Bean时创建新实例 | 每个HTTP请求创建一个实例 |
使用环境 | 任何Spring环境 | 仅Web环境(需要HTTP请求上下文) |
代理模式 | 不需要代理 | 必须使用代理模式 |
生命周期管理 | Spring不管理销毁 | 请求结束时自动销毁 |
性能 | 每次创建有开销 | 请求期间复用,性能更好 |
线程安全 | 每个实例独立,天然线程安全 | 请求级别隔离,线程安全 |
使用场景
Prototype适用于:
- 需要每次都是全新状态的对象
- 有状态的Bean,需要避免共享
- 独立应用程序(非Web环境)
Request适用于:
- Web应用中需要在整个请求过程中保持状态
- 请求级别的缓存或临时数据
- 用户认证信息、请求参数等
项目中已经很好地演示了这两种作用域的使用方式,PrototypeBean
用于演示每次获取都是新实例,而RequestScopeBean
用于Web环境中的请求级别Bean管理。
结果