题目
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
>
> 
需要注意的是,**只有作用域为 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
> ```
>
> 
## 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 都有不同的会话。
