Bean的作用域
Bean的作用域决定了Spring容器创建和管理Bean实例的方式和生命周期。
六种作用域
singleton - 单例(默认)
整个Spring容器中只存在一个Bean实例。
Java
@Component
// 默认就是singleton
public class UserService {
}
// 或显式指定
@Scope("singleton")
@Component
public class UserService {
}
Java
// 验证单例
UserService u1 = context.getBean(UserService.class);
UserService u2 = context.getBean(UserService.class);
System.out.println(u1 == u2); // true
prototype - 多例
每次获取Bean时创建新实例。
Java
@Scope("prototype")
@Component
public class PrototypeBean {
}
// 验证多例
PrototypeBean b1 = context.getBean(PrototypeBean.class);
PrototypeBean b2 = context.getBean(PrototypeBean.class);
System.out.println(b1 == b2); // false
request - 请求作用域
每个HTTP请求创建一个Bean实例,仅适用于Web应用。
Java
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class RequestScopedBean {
}
session - 会话作用域
每个HTTP Session创建一个Bean实例,仅适用于Web应用。
Java
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class SessionScopedBean {
}
application - 应用作用域
整个ServletContext生命周期内一个实例。
Java
@Scope(value = WebApplicationContext.SCOPE_APPLICATION)
@Component
public class ApplicationScopedBean {
}
websocket - WebSocket作用域
每个WebSocket会话一个实例。
Java
@Scope("websocket")
@Component
public class WebSocketScopedBean {
}
作用域对比
| 作用域 | 实例数量 | 生命周期 | 适用场景 |
|---|---|---|---|
| singleton | 1个 | 容器启动到关闭 | 无状态Bean、工具类 |
| prototype | 每次获取创建新实例 | 由使用者管理 | 有状态Bean |
| request | 每个HTTP请求1个 | HTTP请求周期 | 请求参数处理 |
| session | 每个Session 1个 | Session周期 | 用户会话信息 |
| application | 整个应用1个 | ServletContext周期 | 全局配置 |
注解配置
@Scope注解
Java
// 基本用法
@Scope("prototype")
// 使用常量
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
// Web作用域
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
代理模式
当单例Bean注入prototype Bean时,需要使用代理。
Java
@Service
public class OrderService {
// 需要代理,否则每次获取的都是同一个实例
@Autowired
@Lazy
private PrototypeBean prototypeBean;
}
// 或在原型Bean上配置代理
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
@Component
public class PrototypeBean {
}
XML配置
XML
<!-- singleton -->
<bean id="userService" class="com.example.UserService" scope="singleton"/>
<!-- prototype -->
<bean id="prototypeBean" class="com.example.PrototypeBean" scope="prototype"/>
<!-- request -->
<bean id="requestBean" class="com.example.RequestBean" scope="request"/>
注意事项
prototype Bean的生命周期不由Spring完全管理,Spring只负责创建,不负责销毁。
Java
@Scope("prototype")
@Component
public class PrototypeBean {
@PreDestroy // 不会被执行!
public void destroy() {
System.out.println("销毁");
}
}
要点总结
- singleton是默认作用域,容器中只有一个实例
- prototype每次获取都创建新实例
- request/session/application适用于Web应用
- 单例注入prototype需要使用代理模式
- prototype Bean的销毁方法不会被Spring调用
📝 发现内容有误?点击此处直接编辑