Springboot中的Bean作用域

22-12-04 banq

在 Spring 上下文中,bean 是将由 spring 的 ApplicationContext 创建和管理的类的实例。在spring-boot中,当我们对一个类进行@Component注解时,该类就有资格被spring的ApplicationContext管理。
当 spring 容器启动时,它会扫描所有由@Component注释注释的类,然后创建该类的 bean。然后当你声明字段级或构造器级依赖注入时,bean 工厂将获取实例并注入它。

什么是Bean 作用域scope
Bean作用域是我们用@Scope注解定义的,它告诉应用程序上下文应该如何在整个应用程序生命周期中创建和展示特定的Bean。
作为一个例子,spring的默认Bean范围是一个单子单例。
单子单例意味着当应用程序上下文启动时,一个特定的Bean将被一次性创建,并在整个应用程序上下文中使用该Bean。

Spring中的Bean作用域

1、Singleton (默认作用域)

当你只用@Component注解一个类,而没有@Scope注解时,这种类型的Bean将被创建。
在这个作用域中,当应用程序启动时,一个特定的Bean将被一次性创建,并在整个应用程序中使用这个Bean。
这也适用于方法级Bean的创建。这意味着当我们在方法上使用@Bean注解时。

2、原型
在@Component注解之后,用@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)进行注解,这种原型类型的Bean将被创建。
在这个范围内,一个特定类的新实例将被创建并在每次请求该类的Bean时被注入。
这同样适用于方法级Bean的创建。这意味着当我们在方法上使用@Bean注解时,我们需要定义@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS) 

3、请求
在@Component注解之后,用@Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)进行注解,这种请求类型的bean将被创建。
这个范围不适用于普通的独立应用程序。这只适用于java web应用程序的上下文。
在这个作用域内,一个特定类的新实例将被创建并为每个新的HTTP请求注入。

这将同样适用于方法级Bean的创建。这意味着当我们在方法上使用@Bean注解时,我们需要定义@Scope(value=WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS) 

4、会话
当你用@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)进行注解时,这种类型的bean将被创建。
这个作用域不适用于普通的独立应用程序。这将适用于java web应用程序的上下文。
在这个作用域内,一个特定类的新实例将被创建并为HTTP请求的每个新会话注入。
这将同样适用于方法级Bean的创建。这意味着当我们在方法上使用@Bean注解时,我们需要定义@Scope(value=WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS) 

5、Application
当你用@Scope(value=WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)进行注解,这种类型的bean将被创建。
在这个作用域内,一个特定类的新实例将被创建,并为每个新的Web应用运行时间注入。
这与singleton更为相似,但在singleton中,每个ApplicationContext有一个实例,而这里是每个ServletContext有一个实例。

6、自定义范围
与其在spring-boot中使用预定义的作用域,我们可以创建自己的作用域并使用它。
在org.springframework.beans.factory.config包中有一个名为Scope的接口。我们需要从该接口实现我们自己的scope类。

为何需要?
了解这个 bean 作用域将在以下情况下帮助我们。
1、单例

  • 如果您要在 Web 应用程序上下文中保存、更新和使用特定于 Web 应用程序的内容,那么单例是最好的使用作用域。
  • 使用此范围将节省内存,因为它将为 Web 应用程序上下文创建一个 bean。因此,除非您有某些特定要求,否则最好坚持使用此范围。
  • 如果该类要提供一些功能性目的而不是为对象到对象存储一些特定变量,则最好使用此范围。更好地用于服务、存储库和实用程序类,因为这些类型的类主要具有函数而不是字段。


2、原型
  • 如果您需要使用一些有状态的组件,那么这是一个很好的使用范围。
  • 如果您需要使用具有非相互依赖输入的线程或异步流,那么这是在线程内部使用的一个很好的 bean 作用域。


3、请求
  • 如果您需要一个有状态组件来存储一些特定于 HTTP 请求的详细信息,那么这就是您应该选择的作用域。
  • 如果您需要存储一些请求标头或 Auth 令牌并在稍后的流程中使用它们,那么这就是您应该选择的作用域。
  • 如果您需要在程序的每个步骤或每个类中存储请求-响应的值,那么这就是您应该用于特定对象的响应 bean 的作用域。


4、会话
  • 如果您需要一个有状态组件来存储一些特定于会话的详细信息,那么这就是您应该选择的作用域。
  • 如果您需要存储一些当前会话用户信息并在整个会话活动中使用这些详细信息,那么这是理想的使用作用域。


5、Application
  • 如果您需要跨多个 Web 应用程序上下文存储和访问详细信息,则不能使用单例,但可以使用此应用程序作用域 bean。
  • 一个 servlet 上下文可以有多个 Web上下文。