[Java]03.Spring Bean作用域

Bean 的范围:

范围 描述
singleton (默认)将单个 bean 定义范围限定为每个 Spring IoC 容器的单个对象实例。
prototype 将单个 bean 定义范围限定为任意数量的对象实例。
request 将单个 bean 定义范围限定为单个 HTTP 请求的生命周期。也就是说,每个 HTTP 请求都有自己的 bean 实例,该 bean 实例是在单个 bean 定义的后面创建的。仅在 web-aware Spring 的上下文中有效ApplicationContext
session 将单个 bean 定义范围限定为 HTTP 的生命周期Session。仅在 web-aware Spring 的上下文中有效ApplicationContext
application 将单个 bean 定义范围限定为ServletContext. 仅在 web-aware Spring 的上下文中有效ApplicationContext
websocket 将单个 bean 定义范围限定为WebSocket. 仅在 web-aware Spring 的上下文中有效ApplicationContext

单例作用域

当您定义一个 bean 定义并且它的作用域是一个单例时,Spring IoC 容器会创建该 bean 定义定义的对象的一个实例。该单个实例存储在此类单例 bean 的缓存中,并且对该命名 bean 的所有后续请求和引用都返回缓存对象。下图显示了单例范围的工作原理:

单身人士

Spring 的单例 bean 概念不同于四人组 (GoF) 模式书中定义的单例模式。GoF 单例对对象的范围进行了硬编码,以便每个 ClassLoader 只创建一个特定类的一个实例。Spring 单例的范围最好描述为每个容器和每个 bean。这意味着,如果您在单个 Spring 容器中为特定类定义一个 bean,则 Spring 容器会创建该 bean 定义定义的类的一个且仅一个实例。单例作用域是 Spring 中的默认作用域。要将 bean 定义为 XML 中的单例,您可以定义一个 bean,如下例所示:





原型范围

bean 部署的非单一原型范围导致每次对特定 bean 发出请求时都会创建一个新 bean 实例。也就是说,bean 被注入到另一个 bean 中,或者您通过getBean()容器上的方法调用来请求它。通常,您应该对所有有状态 bean 使用原型作用域,对无状态 bean 使用单例作用域。

下图说明了 Spring 原型范围:

原型

(数据访问对象 (DAO) 通常不配置为原型,因为典型的 DAO 不保存任何对话状态。我们更容易重用单例图的核心。)

以下示例将 bean 定义为 XML 中的原型:


与其他作用域相比,Spring 不管理原型 bean 的完整生命周期。容器实例化、配置和以其他方式组装原型对象并将其交给客户端,没有该原型实例的进一步记录。因此,尽管在所有对象上调用初始化生命周期回调方法,而不管范围如何,但在原型的情况下,不会调用配置的销毁生命周期回调。客户端代码必须清理原型范围内的对象并释放原型 bean 持有的昂贵资源。要让 Spring 容器释放原型作用域 bean 持有的资源,请尝试使用自定义bean post-processor,它保存对需要清理的 bean 的引用。

在某些方面,Spring 容器在原型作用域 bean 方面的角色是 Javanew运算符的替代品。超过该点的所有生命周期管理都必须由客户端处理。

请求、会话、应用程序和 WebSocket 范围

requestsessionapplication,和websocket范围只有当你使用一个基于web的Spring在ApplicationContext实现(例如 XmlWebApplicationContext)。如果将这些作用域与常规 Spring IoC 容器(例如 )一起使用ClassPathXmlApplicationContextIllegalStateException则会抛出抱怨未知 bean 作用域的 。

请求范围

考虑以下 bean 定义的 XML 配置:


Spring 容器LoginAction通过loginAction对每个 HTTP 请求使用bean 定义来创建bean 的新实例。也就是说, loginActionbean 的范围在 HTTP 请求级别。您可以根据需要更改所创建实例的内部状态,因为从同一loginActionbean 定义创建的其他实例看不到这些状态更改。它们是针对个人要求的。当请求完成处理时,该请求范围内的 bean 将被丢弃。

当使用注解驱动的组件或 Java 配置时,@RequestScope注解可用于将组件分配给request作用域。以下示例显示了如何执行此操作:

@RequestScope
@Component
public class LoginAction {
    // ...
}
会话范围

考虑以下 bean 定义的 XML 配置:


Spring 容器UserPreferences通过在userPreferences单个 HTTP 的生命周期中使用bean 定义来创建bean 的新实例Session。换句话说,userPreferencesbean 有效地限定在 HTTPSession级别。与请求范围的 bean 一样,您可以根据需要更改所创建实例的内部状态,因为知道其他Session也在使用从相同userPreferencesbean 定义创建的实例的HTTP实例不会看到这些状态更改,因为它们特定于单个 HTTP Session。当 HTTPSession最终被丢弃时,作用域为该特定 HTTP 的 bean Session也将被丢弃。

当使用注解驱动的组件或 Java 配置时,您可以使用 @SessionScope注解将组件分配给session作用域。

@SessionScope
@Component
public class UserPreferences {
    // ...
}
应用程序范围

考虑以下 bean 定义的 XML 配置:


Spring 容器AppPreferences通过appPreferences对整个 Web 应用程序使用一次 bean 定义来创建bean 的新实例。也就是说, appPreferencesbean 的作用域在ServletContext级别并存储为常规 ServletContext属性。这有点类似于 Spring 单例 bean,但在两个重要方面有所不同:它是一个单例 per ServletContext,而不是 per Spring ApplicationContext(在任何给定的 Web 应用程序中可能有多个),并且它实际上是公开的,因此作为一个ServletContext属性可见.

当使用注解驱动的组件或 Java 配置时,您可以使用 @ApplicationScope注解将组件分配给application作用域。以下示例显示了如何执行此操作:

@ApplicationScope
@Component
public class AppPreferences {
    // ...
}

以上文档来自Spring官方网站,关于 Spring-framework 文档 Bean作用域介绍。

你可能感兴趣的:([Java]03.Spring Bean作用域)