【SpringBoot笔记10】Spring中Bean的6种作用域
参考:官方文档1 Bean的作用域在Spring Framework中,总共定义了6种bean 的作用域,其中有4种作用域只有当应用为web应用的时候才有效,并且Spring还支持自定义作用域。下表描述了这6种作用域:ScopeDescriptionsingleton(默认的)在每个Spring IoC容器中,一个bean定义对应只会有唯一的一个bean实例。...
参考:官方文档
1 Bean的作用域
在Spring Framework
中,总共定义了6种bean
的作用域,其中有4种作用域只有当应用为web
应用的时候才有效,并且Spring
还支持自定义作用域。
下表描述了这6种作用域:
Scope | Description |
---|---|
singleton | (默认的)在每个Spring IoC 容器中,一个bean 定义对应只会有唯一的一个bean 实例。 |
prototype | 一个bean 定义可以有多个bean 实例。 |
request | 一个bean 定义对应于单个HTTP 请求的生命周期。也就是说,每个HTTP 请求都有一个bean 实例,且该实例仅在这个HTTP 请求的生命周期里有效。该作用域仅适用于WebApplicationContext 环境。 |
session | 一个bean 定义对应于单个HTTP Session 的生命周期,也就是说,每个HTTP Session 都有一个bean 实例,且该实例仅在这个HTTP Session 的生命周期里有效。该作用域仅适用于WebApplicationContext 环境。 |
application | 一个bean 定义对应于单个ServletContext 的生命周期。该作用域仅适用于WebApplicationContext 环境。 |
websocket | 一个bean 定义对应于单个websocket 的生命周期。该作用域仅适用于WebApplicationContext 环境。 |
1.1 singleton作用域
singleton
作用域表示在整个Spring
容器中一个bean
定义只生成了唯一的一个bean
实例,被Spring
容器管理。所有对这个bean
的请求和引用都会返回这个bean
实例。
下面的图说明了singleton
作用域是如何工作的:
上图中,有3个地方引用了这个
bean
,这3个引用指向的都是同一个bean
实例。
singleton
作用域是Spring
中默认的作用域,可以在定义bean
的时候指定或者不指定都可以,如下:
<!-- 不指定作用域,默认是singleton -->
<bean id="accountService" class="com.something.DefaultAccountService"/>
<!-- 显示指定作用域为singleton -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
1.2 prototype作用域
prototype
作用域表示的是一个bean
定义可以创建多个bean
实例,有点像一个类可以new
多个实例一样。
也就是说,当注入到其他的bean
中或者对这个bean
定义调用getBean()
时,都会生成一个新的bean
实例。
作为规则,应该对所有有状态的
bean
指定prototype
作用域,对所有无状态的bean
指定singleton
作用域。
下图描述了prototype
作用域是如何工作的:
上图中,每个引用对应一个新的
bean
实例。请注意,上图中的例子不适用于生产环境。因为
DAO
通常来说是无状态的bean
,应该指定它的作用域为singleton
比较合适。
在xml
中可以这样定义prototype
作用域:
<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
和其他作用域不同的是,
Spring
并不管理作用域为prototype
的bean
的整个生命周期。Spring
容器实例化它、配置它、组装它,然后就将bean
交给给使用者了,之后就不会对这个bean
进行管理了。因此,Spring
不会调用该bean
的销毁生命周期回调,使用者必须自己销毁 这个bean
并释放资源。如果想让Spring
来销毁它并释放资源,请使用自定义的bean post-processor
。
1.3 当singleton的bean依赖prototype的bean
当singleton
的bean
依赖prototype
的bean
时,请注意,这个依赖关系是在实例化时候解析的,并且只解析一次。因此,每个依赖的prototype
的bean
都是一个新的bean
实例。
然而,如果一个singleton
的bean
想要在运行时,在每次注入时都能有一个新的prototype
的bean
生成并注入,这是不行的。因为依赖注入在初始化的时候只会注入一次。如果想要在运行时多次注入新的prototype
的bean
,请参考Method Injection。
1.4 request、session、application、websocket作用域
request
、session
、application
、websocket
作用域只有在web
环境下才有用。
1.4.1 初始化web配置
为了支持request
、session
、application
、websocket
作用域,在定义bean
之前需要一些初始化配置。
如何完成这个初始化配置取决于你的特定Servlet
环境。
如果你在Spring Web MVC
中定义这4中作用域,不需要进行初始化配置。因为,Spring
使用的DispatcherServlet
已经公开了所有相关的状态。
如果你使用的是Servlet 2.5
web容器,这些容器不使用Spring
的DispatcherServlet
,你需要注册org.springframework.web.context.request.RequestContextListener
。对于Servlet 3.0+
的web容器,可以通过编程的方式使用WebApplicationInitializer
接口来完成,或者使用xml
配置:
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
如果监听器设置遇到问题,可以考虑配置Spring
的RequestContextFilter
:
<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>
DispatcherServlet
、RequestContextListener
和RequestContextFilter
共同做了相同的事,即将HTTP
请求对象绑定到服务该请求的线程。这使得请求作用域和会话作用域的bean在调用链的更下游可用。
1.4.2 request作用域
下面的xml
配置指定了bean
的作用域为request
:
<bean id="loginAction" class="com.something.LoginAction" scope="request"/>
Spring
为每一个HTTP
请求创建一个新的LoginAction
的bean
。每个bean
之间不可见,当请求结束,对应的bean
将被丢弃。
当使用注解定义bean
的时候,可以通过使用@RequestScope
注解设定request
作用域:
@RequestScope
@Component
public class LoginAction {
// ...
}
1.4.3 session作用域
在xml
中可以这样定义bean
的作用域为session
作用域:
<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>
Spring
为每个HTTP Session
创建一个新的UserPreferences
的bean
。每个bean
之间是不可见的,只属于对应的Session
,当Session
销毁的时候,对应的bean
也会被销毁。
当使用注解定义bean
的时候,可以通过@SessionScope
注解设定session
作用域:
@SessionScope
@Component
public class UserPreferences {
// ...
}
1.4.4 application作用域
在xml
中可以这样定义bean
的作用域为application
作用域:
<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>
Spring
为整个web
上下文创建一个AppPreferences
的bean
。也就是说,这个bean
作用域是在ServletContext
级别,它是作为ServletContext
的一个属性存在的。
这和singleton
作用域很像,但是有两点不同:
application
作用域的bean
是每个ServletContext
只有一个;而singleton
作用域是每个Spring
的ApplicationContext
只有一个。两者的范围不同。application
作用域的bean
是属于ServletContext
的,作为ServletContext
的属性,是可见的。
当使用注解定义bean
的时候,可以通过@ApplicationScope
注解设定application
作用域:
@ApplicationScope
@Component
public class AppPreferences {
// ...
}
1.4.5 被设定了作用域的bean作为依赖项注入
没太看懂,详见官方文档
更多推荐
所有评论(0)