题目
Bean 的作用域有哪些
答案
@[toc] --- 在定义 Bean 时,用户不但可以配置 Bean 的属性值及相互之间的依赖关系,还可以定义 Bean 的作用域。**作用域将对 Bean 的生命周期和创建方式产生影响。** > **如何配置 bean 的作用域呢?** > > xml 方式: > > ```xml > <bean id="..." class="..." scope="singleton"></bean> > ``` > > 注解方式: > > ```java > @Bean > @Scope("singleton") > public Person personPrototype() { > return new Person(); > } > ``` Bean 的作用域如下 ⬇️ ## singleton(默认) singleton 的 Bean 在同一 Spring 容器中只有一个实例,Spring 中的 bean 默认都是单例的,属于单例设计模式的应用 > 举个例子: > > ```xml > <bean id="car" class="com.smart.scope.Car" scope="singleton"/> 1 > <bean id="bossl" class="com.smart.scope.Boss" p: car-ref="car"/> 2 > <bean id="boss2" class="com.smart.scope.Boss" p: car-ref="car"/> 3 > <bean id="boss3" class="com.smart.scope.Boss" p: car-ref="car"/> 4 > ``` > > 1 处的 car Bean 声明为 singleton(**默认是 singleton,所以其实无须显式指定**),在容器中有 3 个其他的 Bean 引用了 car Bean,如 2、3、4 所示。在容器内部,boss1、boss2 和 boss3 的 car 属性都指向同一个 Bean > > ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/img/image-20220708152040737.png) 需要注意的是,**只有作用域为 Singleton 的 Bean 由 Spring 容器负责管理和维护,而其他作用域的 Bean 需要在适当的时候手动管理其创建和销毁**。 ## prototype 每次通过容器的 getBean 方法返回的都是一个新的 bean 实例。在默认情况下,Spring 容器在启动时不实例化 prototype 的 Bean。此外,Spring 容器将 prototype的 Bean 交给调用者后,就不再管理它的生命周期 > 举个例子: > > ```xml > <bean id="car" class="com.smart.scope.Car" scope="prototype"/> 1 > <bean id="bossl" class="com.smart.scope.Boss" p: car-ref="car"/> 2 > <bean id="boss2" class="com.smart.scope.Boss" p: car-ref="car"/> 3 > <bean id="boss3" class="com.smart.scope.Boss" p: car-ref="car"/> 4 > ``` > > ![](https://cs-wiki.oss-cn-shanghai.aliyuncs.com/img/image-20220708152149157.png) ## request 每一次 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP request 内有效。 ## session 每一次来自新 session 的 HTTP 请求都会产生一个新的 bean,该 bean 仅在当前 HTTP session 内有效。 假设我们有一个用户登录的功能,需要在用户的整个会话期间保持用户的登录状态。 在这种情况下,可以将用户对象的作用域设置为 Session,以便在同一个用户的不同请求之间共享同一个用户对象。这样可以确保用户的登录状态在整个会话期间保持一致。 ```java @Component @Scope("session") public class User { // ... } ``` ## global-session 全局 session 作用域,仅仅在基于 portlet 的 web 应用中才有意义,Spring5 已经没有了。Portlet 是能够生成语义代码(例如:HTML)片段的小型 Java Web 插件。它们基于 portlet 容器,可以像 servlet 一样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不同的会话。