💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# Spring 5 – Bean 范围 > 原文: [https://howtodoinjava.com/spring-core/spring-bean-scopes/](https://howtodoinjava.com/spring-core/spring-bean-scopes/) 在 Spring 框架中,我们可以在 6 个内置的 **spring bean 范围**中创建 bean,还可以定义**自定义 bean 作用域**。 在这六个范围中,只有当您使用网络感知`ApplicationContext`时,四个才可用。 `singleton`和`prototype`范围在任何类型的 IOC 容器中都可用。 ## 1\. Spring Bean 范围类型 在 Spring 中,可以使用 spring bean `@Scope`注解定义范围。 让我们快速列出所有六个可在 Spring 应用程序上下文中使用的内置 bean 范围。 这些相同的范围也适用于 SpringBoot bean 范围。 | 范围 | 描述 | | --- | --- | | `singleton`(默认) | 每个 spring IoC 容器一个 bean 对象实例 | | `prototype` | 与单例相反,每次请求 bean 时,它都会产生一个新实例。 | | `request` | 将创建一个单例,并在 HTTP 请求的整个生命周期中可用。仅在可感知网络的 Spring `ApplicationContext`中有效。 | | `session` | 一个单例将在 HTTP 会话的整个生命周期中创建并可用。仅在可感知网络的 Spring `ApplicationContext`中有效。 | | `application` | 一个单例将在`ServletContext`的整个生命周期中创建并可用。仅在可感知网络的 Spring `ApplicationContext`中有效。 | | `websocket` | 一个单例将在`WebSocket`的整个生命周期中创建并可用。仅在可感知网络的 Spring `ApplicationContext`中有效。 | #### 1.1. 单例范围 `singleton`是 spring 容器中的默认 bean 作用域。 它告诉容器每个容器仅创建和管理一个 bean 类实例。 该单个实例存储在此类[单例](https://howtodoinjava.com/design-patterns/creational/singleton-design-pattern-in-java/) Bean 的缓存中,并且对该命名 Bean 的所有后续请求和引用都返回该缓存的实例。 使用 Java 配置的单例作用域 bean 的示例: ```java @Component //This statement is redundant - singleton is default scope @Scope("singleton") //This statement is redundant public class BeanClass { } ``` 使用 XML 配置的单例作用域 bean 的示例: ```java <!-- To specify singleton scope is redundant --> <bean id="beanId" class="com.howtodoinjava.BeanClass" scope="singleton" /> //or <bean id="beanId" class="com.howtodoinjava.BeanClass" /> ``` #### 1.2. 原型范围 每当应用程序代码对 Bean 进行请求时,`prototype`范围都会导致创建新的 Bean 实例。 您应该知道,销毁[ bean 生命周期方法](https://howtodoinjava.com/spring/spring-core/spring-bean-life-cycle/)没有被称为`prototype`作用域 bean,仅调用了初始化回调方法。 因此,作为开发人员,您需要负责清理原型作用域的 Bean 实例以及其中包含的所有资源。 原型 bean 范围的 Java 配置示例: ```java @Component @Scope("prototype") public class BeanClass { } ``` 原型 bean 范围的 XML 配置示例: ```java <bean id="beanId" class="com.howtodoinjava.BeanClass" scope="prototype" /> ``` 通常,您应该对所有有状态 Bean 使用`prototype`范围,而对无状态Bean使用`singleton`范围。要在请求,会话,应用程序和 Websocket 范围中使用 Bean,您需要注册[`RequestContextListener`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/context/request/RequestContextListener.html)或者[`RequestContextFilter`](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/RequestContextFilter.html)。 #### 1.3. 请求范围 在`request`范围内,容器为每个 HTTP 请求创建一个新实例。 因此,如果服务器当前正在处理 50 个请求,则容器最多可以具有 50 个单独的 Bean 类实例。 对一个实例的任何状态更改,对其他实例都不可见。 请求完成后,这些实例将被销毁。 请求 bean 范围的 Java 配置示例: ```java @Component @Scope("request") public class BeanClass { } //or @Component @RequestScope public class BeanClass { } ``` 请求 bean 范围的 XML 配置示例: ```java <bean id="beanId" class="com.howtodoinjava.BeanClass" scope="request" /> ``` > 阅读更多: [Web 服务器如何工作?](https://howtodoinjava.com/server/tomcat/a-birds-eye-view-on-how-web-servers-work/) #### 1.4. 会话范围 在`session`范围内,容器为每个 HTTP 会话创建一个新实例。 因此,如果服务器有 20 个活动会话,则容器最多可以具有 20 个 Bean 类的单独实例。 单个会话生存期内的所有 HTTP 请求都可以访问该会话范围内的同一单个 Bean 实例。 对一个实例的任何状态更改,对其他实例都不可见。 一旦会话在服务器上销毁/结束,这些实例将被销毁。 会话 bean 范围的 Java 配置示例: ```java @Component @Scope("session") public class BeanClass { } //or @Component @SessionScope public class BeanClass { } ``` 会话 bean 范围的 XML 配置示例: ```java <bean id="beanId" class="com.howtodoinjava.BeanClass" scope="session" /> ``` #### 1.5. 应用范围 在`application`范围内,容器为每个 Web 应用程序运行时创建一个实例。 它几乎与`singleton`示波器相似,只有两个区别,即 1. `application`范围的 bean 是每个`ServletContext`单身,而`singleton`范围的 bean 是每个`ApplicationContext`单身。 请注意,单个应用程序可以有多个应用程序上下文。 2. `application`范围内的 bean 作为`ServletContext`属性可见。 应用程序 bean 范围的 Java 配置示例: ```java @Component @Scope("application") public class BeanClass { } //or @Component @ApplicationScope public class BeanClass { } ``` 应用程序 bean 范围的 XML 配置示例: ```java <bean id="beanId" class="com.howtodoinjava.BeanClass" scope="application" /> ``` #### 1.6. websocket 范围 [WebSocket 协议](https://tools.ietf.org/html/rfc6455)允许客户端与已选择与客户端通信的远程主机之间进行双向通信。 WebSocket 协议为双向通信提供单个 TCP 连接。 这对于同时编辑和多用户游戏的多用户应用程序特别有用。 在这种类型的 Web 应用程序中,HTTP 仅用于初始握手。 如果服务器同意,服务器可以以[ HTTP 状态 101(交换协议)](https://restfulapi.net/http-status-codes/)进行响应。 如果握手成功,则 TCP 套接字保持打开状态,客户端和服务器都可以使用该套接字向彼此发送消息。 websocket bean 作用域的 Java 配置示例: ```java @Component @Scope("websocket") public class BeanClass { } ``` Websocket bean 作用域的 XML 配置示例: ```java <bean id="beanId" class="com.howtodoinjava.BeanClass" scope="websocket" /> ``` 请注意,`websocket`范围内的 bean 通常是单例的,并且比任何单独的 WebSocket 会话的生存期都更长。 ## 2\. 自定义线程范围 Spring 还使用类`SimpleThreadScope`提供了非默认`thread`范围。 要使用此作用域,必须使用`CustomScopeConfigurer`类将其注册到容器。 ```java <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"> <property name="scopes"> <map> <entry key="thread"> <bean class="org.springframework.context.support.SimpleThreadScope"/> </entry> </map> </property> </bean> ``` 对 bean 的每个请求都将在同一线程中返回相同的实例。 线程 bean 范围的 Java 配置示例: ```java @Component @Scope("thread") public class BeanClass { } ``` 线程 bean 范围的 XML 配置示例: ```java <bean id="beanId" class="com.howtodoinjava.BeanClass" scope="thread" /> ``` ## 3\. 总结 Spring 框架提供了六个 Spring bean 作用域,并且实例在每个作用域内具有不同的生命周期跨度。 作为开发人员,我们必须明智地选择任何容器管理的 bean 的范围。 同样,当具有不同作用域的 bean 相互引用时,我们必须做出明智的决定。 试着记住上面给出的所有信息,以回答任何 SpringBean 范围面试问题。 学习愉快!