昨天的面试让我对 Spring Boot 的核心注解有了更深的理解,复盘时不仅完善了 @SpringBootConfiguration 的定制和 @EnableAutoConfiguration 的条件注解细节,还想到一个相关但没被问到的知识点:Bean 的作用域(Scope)。在 Spring 中,Bean 的作用域决定了它的生命周期和实例化方式,这对理解 Spring 容器管理非常重要。面试官虽然没问,但我复盘时觉得这是个高频考点,值得整理一下,算是给自己加个"隐藏分"。
前文回顾(略)
之前已经聊了 @SpringBootApplication 的三个子注解:@SpringBootConfiguration(定制化配置)、@EnableAutoConfiguration(自动配置与条件注解)、@ComponentScan(组件扫描)。这些注解共同管理了 Bean 的创建和注入,而 Bean 的作用域则是另一个关键维度。下面就详细说说。
Bean 的 Scope 作用域及其范围
在 Spring 中,Bean 的作用域通过 @Scope 注解定义,默认是 singleton。但 Spring 提供了多种作用域,适用于不同场景。以下是常见的 Scope 类型及其范围:
-
singleton(单例)- 作用:整个应用中只有一个实例,所有对该 Bean 的引用都指向同一个对象。
- 范围:Spring 容器全局唯一,Bean 在容器启动时创建,销毁时释放。
- 使用场景 :无状态的服务类或工具类,比如
UserService,适合共享使用。 - 细节 :可以通过
@Scope("singleton")显式指定,但默认就是这个,所以很少写。
-
prototype(原型)- 作用:每次请求该 Bean 时,都会创建一个新实例。
- 范围 :每次注入或通过
getBean获取时独立创建,生命周期由调用方管理(Spring 不负责销毁)。 - 使用场景 :有状态的对象,比如每次请求需要独立数据的
UserContext。 - 细节 :用
@Scope("prototype")指定。复盘时想到,如果面试官问"prototype 的销毁怎么办",可以回答"Spring 不管,需要开发者手动清理或交给垃圾回收"。
-
request(请求)- 作用:每个 HTTP 请求创建一个独立实例,请求结束后销毁。
- 范围:仅限于 Web 应用,绑定到单个 HTTP 请求的生命周期。
- 使用场景:Web 开发中需要请求隔离的数据,比如当前请求的用户信息。
- 细节 :需要引入
spring-web依赖,用@Scope("request")指定。
-
session(会话)- 作用:每个 HTTP 会话创建一个独立实例,会话结束后销毁。
- 范围:Web 应用的会话级别,通常跨多个请求。
- 使用场景:用户的登录状态或购物车数据。
- 细节 :同样需要 Web 环境支持,用
@Scope("session")。
-
application(应用)- 作用 :整个 Web 应用中只有一个实例,类似于
singleton,但绑定到 Servlet 上下文。 - 范围:ServletContext 的生命周期,通常在 Web 容器启动时创建。
- 使用场景:全局配置或计数器。
- 细节 :用
@Scope("application"),比singleton更明确地表示 Web 应用级别。
- 作用 :整个 Web 应用中只有一个实例,类似于
-
websocket(WebSocket)(Spring 4.1+)- 作用:每个 WebSocket 会话创建一个实例。
- 范围:绑定到 WebSocket 连接的生命周期。
- 使用场景:实时通信场景,比如聊天应用。
- 细节 :用
@Scope("websocket"),比较小众,但可能是个加分点。
配置方式
在 Spring Boot 中,定义 Bean 的作用域通常有两种方式:
-
注解方式 :在
@Bean或@Component上加@Scope,比如:java@Bean @Scope("prototype") public UserContext userContext() { return new UserContext(); } -
XML 方式 :老项目可能用
<bean scope="prototype">,但 Spring Boot 基本不用了。
复盘感想
Bean 的作用域虽然这次没被问到,但它是 Spring 核心知识的一部分,跟 @SpringBootConfiguration 定义 Bean 的过程息息相关。如果面试官追问"单例和原型的区别",我可以回答:"单例是全局共享,原型是每次独立创建,适合有状态对象。"如果再问"Web 场景下用哪个",我可以自信地说"request 或 session,看需求隔离级别"。
复盘时还想到一个小细节:singleton 和 application 的区别容易混淆,前者是 Spring 容器级别,后者是 Servlet 上下文级别,Web 项目中可能有细微差异。
总结
加上 Bean 的作用域,这次复盘更全面了。@SpringBootApplication 通过子注解管理 Bean 的创建,而 Scope 决定了 Bean 的生命周期和实例化范围。常见的作用域包括:
singleton:全局单例,默认。prototype:每次新实例。- Web 专属:
request、session、application。
下次面试如果遇到类似问题,我会更有底气,甚至可以主动抛出"Bean 的作用域您想让我展开吗?"这样的反问,争取多展示一些知识面。这次复盘让我对 Spring 的掌控感又提升了一步!