Spring Bean作用域
使用Spring bean定义,Spring容器不仅实例化bean并连接其依赖关系,还提供了从特定bean定义创建的对象的范围。 Spring框架对六个Spring bean范围提供了内置支持。在这六个bean范围中,只有当我们使用可识别Web的ApplicationContext时,才有四个可用。我们还可以创建自定义范围。
Spring bean支持的作用域(范围)
单例作用域–为每个Spring IoC容器创建一个与bean定义相对应的单个对象实例。 Singleton范围是默认的bean范围。
原型作用域–每次从Spring容器请求bean时都会创建一个新的对象实例。
请求作用域–为每个HTTP请求创建一个新的bean实例。此Spring bean范围仅在可感知网络的Spring ApplicationContext的上下文中有效。
会话作用域–单个bean实例的范围是HTTP会话的生命周期。该范围仅在可感知网络的Spring ApplicationContext的上下文中有效。
应用程序作用域–将单个bean定义范围限定为ServletContext的生命周期。该范围仅在可感知网络的Spring ApplicationContext的上下文中有效。
Websocket作用域–将单个bean定义的范围扩展到WebSocket的生命周期。该范围仅在可感知网络的Spring ApplicationContext的上下文中有效。
Spring Bean的单例范围
当我们将一个bean限定为一个单例时,Spring容器将为该bean定义所定义的对象创建一个实例。对ID与该bean定义匹配的ID的所有请求都将导致该特定的bean实例由Spring容器返回。
Singleton作用域是Spring中的默认作用域,如果我们未在bean定义中提供bean作用域,则将bean作为作用域创建。
请注意,Spring单例的范围是每个容器和每个bean。尽管Spring容器创建了该bean定义所定义的类的一个实例,并且只有一个实例,但是我们仍然可以创建该bean的其他对象,这些对象不受Spring容器的管理。
单例作用域Bean的XML配置示例
<bean id="abcBean" class="com.theitroad.BeanService" scope="singleton"/>
它等同于以下定义,因为单例作用域是默认作用域
<bean id="abcBean" class="com.theitroad.BeanService"/>
使用@Scope注释定义单例作用域的bean
@Service @Scope("singleton") public class BeanService{ ... ... }
Spring bean原型范围
当一个bean的作用域是原型时,每次请求该特定bean时都会创建一个新的bean实例。
Spring不能管理原型Bean的完整生命周期。对于原型作用域的bean,将调用生命周期回调方法,但不会调用已配置的销毁生命周期回调方法。客户端代码负责清理原型作用域内的对象并释放原型bean所拥有的资源。
原型范围内的bean-的XML配置示例
<bean id="abcBean" class="com.theitroad.BeanService" scope="prototype"/>
使用注解定义原型作用域bean
@Service @Scope("prototype") public class BeanService{ ... ... }
Request作用域
对于请求范围的bean,Spring容器为每个HTTP请求创建一个新的bean实例。这些实例特定于单个请求,并且在请求完成处理后,实例将被销毁。
请求范围的bean-的XML配置示例
<bean id="abcBean" class="com.theitroad.BeanService" scope="request"/>
如果要使用注释,则可以使用@RequestScope注释将组件分配给请求范围,也可以使用@Scope(WebApplicationContext.SCOPE_REQUEST)。
@RequestScope @Service public class BeanService{ ... ... }
Session作用域
对于会话范围的bean,Spring容器在单个HTTP Session的生存期内创建该bean的新实例。这意味着bean的作用域位于HTTP会话级别,并且在丢弃该特定HTTP会话时将其丢弃。
会话范围的bean-的XML配置示例
<bean id="abcBean" class="com.theitroad.BeanService" scope="session"/>
如果要使用注释,则可以使用@SessionScope注释将组件分配给请求范围,也可以使用@Scope(WebApplicationContext.SCOPE_SESSION)。
@SessionScope @Service public class BeanService{ ... ... }
Application作用域
对于应用程序范围的bean,Spring容器为整个Web应用程序创建一次bean的新实例。这意味着bean的作用域位于ServletContext级别,并存储为常规ServletContext属性。
应用程序范围的bean-的XML配置示例
<bean id="abcBean" class="com.theitroad.BeanService" scope="application"/>
如果要使用注释,则可以使用@ApplicationScope注释将组件分配给请求范围,也可以使用@Scope(WebApplicationContext.SCOPE_APPLICATION)。
@ApplicationScope @Service public class BeanService{ ... ... }
Spring中的WebSocket bean作用域
Spring框架提供了一个WebSocket API,可用于编写处理WebSocket消息的客户端和服务器端应用程序。 WebSocket范围的bean通常是单例的,并且比任何单独的WebSocket会话的生存期更长。因此,我们需要对作用域WebSocket的bean使用作用域代理模式。
@Component @Scope(scopeName = "websocket", proxyMode = ScopedProxyMode.TARGET_CLASS) public class MyBean { ... ... }
对于Spring bean范围请求,会话,应用程序和Websocket,我们需要注册
org.springframework.web.context.request.RequestContextListener。对于Servlet 3.0+,可以使用WebApplicationInitializer接口以编程方式完成此操作。如果我们使用的是Servlet 2.5 Web容器,则必须通过在Web应用程序的web.xml文件中添加以下声明来显式地完成此注册:
<web-app> ... <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> ... </web-app>