11. Spring中的Bean作用域有哪些?每种作用域的特点是什么?
大约 4 分钟
在 Spring 框架中,Bean 的作用域(Scope) 决定了 Bean 的生命周期和可见范围。不同的作用域定义了 Spring 容器如何创建和管理 Bean 实例。Spring 支持多种作用域,每种作用域有其特定的使用场景和特点。
Spring 中的 Bean 作用域
1. Singleton(单例,默认作用域)
特点:
- 单例模式:Spring 容器中每个 Bean 都是单例的,即对于一个 Bean 定义,Spring 容器中只会创建一个实例,并且该实例会被共享使用。
- 生命周期:单例 Bean 的生命周期与 Spring 容器相同。它在 Spring 容器启动时创建,并在容器关闭时销毁。
- 默认作用域:如果不显式指定 Bean 的作用域,Spring 将默认使用 Singleton 作用域。
使用场景:
- 适用于无状态的服务类或通用组件,因为单例模式可以减少资源的开销,且更易于管理。
示例:
@Component
@Scope("singleton") // 该注解可以省略,因为 Singleton 是默认的作用域
public class MyService {
// 业务逻辑
}
2. Prototype(原型)
特点:
- 多实例模式:每次请求该 Bean 时,Spring 容器都会创建一个新的实例。不同的请求将获得不同的 Bean 实例。
- 生命周期:Prototype Bean 的生命周期不由 Spring 容器管理。Spring 容器只负责创建 Bean 实例,并注入依赖关系,不管理其销毁工作。
- 不适用于自动销毁:因为 Spring 容器不管理 Prototype Bean 的完整生命周期,因此
@PreDestroy
等销毁回调方法不会自动调用。
使用场景:
- 适用于有状态的 Bean,例如需要在每次使用时创建新实例的场景。
示例:
@Component
@Scope("prototype")
public class MyPrototypeService {
// 业务逻辑
}
3. Request(请求作用域,Web 应用中使用)
特点:
- 每个 HTTP 请求一个实例:在 Web 应用中,Spring 容器为每个 HTTP 请求创建一个新的 Bean 实例。同一个请求中的多个组件共享同一个 Bean 实例。
- 生命周期:Bean 的生命周期与 HTTP 请求相同,请求结束后,Bean 实例会被销毁。
使用场景:
- 适用于需要在单个 HTTP 请求中维持状态的场景。
示例:
@Component
@Scope("request")
public class MyRequestScopedBean {
// 业务逻辑
}
4. Session(会话作用域,Web 应用中使用)
特点:
- 每个 HTTP 会话一个实例:在 Web 应用中,Spring 容器为每个 HTTP 会话创建一个新的 Bean 实例。同一个会话中的多个请求共享同一个 Bean 实例。
- 生命周期:Bean 的生命周期与 HTTP 会话相同,会话结束后,Bean 实例会被销毁。
使用场景:
- 适用于需要在整个会话期间维持状态的场景。
示例:
@Component
@Scope("session")
public class MySessionScopedBean {
// 业务逻辑
}
5. GlobalSession(全局会话作用域,主要用于 Portlet 应用)
特点:
- Portlet 全局会话作用域:在 Portlet 环境下,每个全局 HTTP 会话(跨多个 Portlet 的会话)会创建一个新的 Bean 实例。
- 生命周期:Bean 的生命周期与全局 HTTP 会话相同,会话结束后,Bean 实例会被销毁。
使用场景:
- 主要用于需要跨多个 Portlet 共享数据的场景。
示例:
@Component
@Scope("globalSession")
public class MyGlobalSessionScopedBean {
// 业务逻辑
}
6. Application(应用作用域,Spring WebFlux 中使用)
特点:
- 每个 ServletContext 一个实例:在 Web 应用中,Spring 容器为每个
ServletContext
创建一个新的 Bean 实例。这意味着一个应用程序的所有请求都共享同一个 Bean 实例。 - 生命周期:Bean 的生命周期与
ServletContext
相同,当 Web 应用关闭时,Bean 实例会被销毁。
使用场景:
- 适用于需要在整个应用程序范围内共享状态的场景。
示例:
@Component
@Scope("application")
public class MyApplicationScopedBean {
// 业务逻辑
}
总结
- Singleton:默认作用域,整个 Spring 容器中只有一个实例,适用于无状态的 Bean。
- Prototype:每次请求都会创建新的实例,适用于有状态的 Bean。
- Request:每个 HTTP 请求创建一个实例,适用于 Web 应用中每个请求需要独立的 Bean。
- Session:每个 HTTP 会话创建一个实例,适用于 Web 应用中每个会话需要维持状态的 Bean。
- GlobalSession:每个全局 HTTP 会话创建一个实例,主要用于 Portlet 环境。
- Application:在整个
ServletContext
中共享一个实例,适用于需要全局共享的 Bean。
选择适当的 Bean 作用域可以有效地管理资源和 Bean 的生命周期,确保应用程序的高效运行。