作用域(@Scope)

Exisi 2022-06-28 08:09:54
Categories: Tags:
  • 配置bean的作用域

 

参数

描述

proxyMode

指定是否应将组件配置为作用域代理,如果是,则代理应基于接口还是基于子类。

scopeName

指定用于带注释的组件/bean 的范围的名称

作用域

描述

singleton

默认作用域。该作用域下的 Bean IoC 容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。

prototype

每次对该作用域下的 Bean 的请求都会创建新的实例,并返回 bean 的不同实例。

request

对于每次HTTP请求,使用request定义的Bean都将产生一个新实例,即每次HTTP请求将会产生不同的Bean实例。

该作用域仅适用于WebApplicationContext环境

session

在一次 Http Session 中,容器会返回该 Bean 的同一实例。而对不同的 Session 请求则会创建新的实例,该 bean 实例仅在当前 Session 内有效。同 Http 请求相同,每一次 session 请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的 session 请求内有效,请求结束,则实例将被销毁。

该作用域仅适用于WebApplicationContext环境

application

在一个 Http Servlet Context 中,定义一个 Bean 实例。

该作用域仅适用于WebApplicationContext环境

websocket

在一个HTTP WebSocket的生命周期中,定义一个Bean实例

value

scopeName的别名

 

  • Spring 容器中,对于 singleton 作用域的 Bean,容器会负责管理其完整的生命周期,包括创建、初始化、依赖注入、使用、销毁等过程。而对于 prototype 作用域的 Bean,由于每次请求都会创建一个新的实例,因此容器无法管理其完整的生命周期。如果 Spring 容器对于每个 prototype 作用域的 Bean 都要管理其完整的生命周期,那么就会导致性能下降和资源浪费。因此,Spring 选择将 prototype 作用域的 Bean 的生命周期交由调用方来管理,以提高性能和资源利用率。这也是为什么在使用 prototype 作用域时需要特别注意 Bean 实例的生命周期和资源占用情况的原因

 

  • Java 在创建 Java 实例时,需要进行内存申请;销毁实例时,需要完成垃圾回收,这些工作都会导致系统开销的增加。因此,prototype 作用域 Bean 的创建、销毁代价比较大。而 singleton 作用域的 Bean 实例一旦创建成功,可以重复使用。因此,除非必要,否则尽量避免将 Bean 被设置成 prototype 作用域。

示例

@Controller

@RequestMapping(/test)

@Scope(prototype)

public class TestController {

}

  • 对有状态的 bean 应该使用 prototype 作用域,而对无状态的bean则应该使用 singleton 作用域

 

  • singleton 作用域在多线程下是不安全的

 

  • 如果将依赖项原型的 bean 依赖项注入到单例范围的 bean 中,则将实例化新的原型 bean,然后将依赖项注入到单例 bean 中。原型实例是曾经提供给单例范围的 bean 的唯一实例。

 

  • 但是,假设希望单例作用域的 bean 在运行时重复获取原型作用域的 bean 的新实例。不能将原型作用域的 bean 依赖项注入到单例 bean 中,因为当 Spring 容器实例化单例 bean 并解析并注入其依赖项时,该注入仅发生一次。如果在运行时多次需要一个原型 bean 的新实例

 

  • 如果使用 Servlet 2.5 Web 容器,并且在 Spring DispatcherServlet之外处理请求(例如,当使用 JSF Struts ),则需要注册org.springframework.web.context.request.RequestContextListener ServletRequestListener。如果使用 Servlet 3.0,可以使用WebApplicationInitializer接口以编程方式完成此操作。对于较旧的容器,将以下声明添加到 Web 应用程序的web.xml文件中:

 

<web-app>
    ...
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    ...
</web-app>

 

  • 如果监听器设置存在问题,请考虑使用 Spring RequestContextFilter。过滤器 Map 取决于周围的 Web 应用程序配置,因此必须适当地对其进行更改。以下清单显示了 Web 应用程序的过滤器部分:

<web-app>

 

    ...
    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

 

 

来自 <https://www.docs4dev.com/docs/zh/spring-framework/5.1.3.RELEASE/reference/core.html#beans-factory-scopes>