spring bean scope
spring bean scope有如下几种取值
scope | 描述 |
singleton | (Default) Scopes a single bean definition to a single object instance per Spring IoC container. |
prototype | Scopes a single bean definition to any number of object instances. |
request | Scopes a single bean definition to the lifecycle of a single HTTP request; that is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
session | Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
globalSession | Scopes a single bean definition to the lifecycle of a global HTTP Session . Typically only valid when used in a Portlet context. Only valid in the context of a web-aware Spring ApplicationContext . |
application | Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
websocket | Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
singleton scope: 一个ioc容器内只有一个bean实例
properte scope:bean的范围为任意个实例,相当于java中的new 操作
request scope:http request生命周期内只有一个bean实例
session scope: http session生命周期内只有一个bean实例
gloableSession scope: http globaleSession生命周期内只有一个bean实例
application scope: 一个servletContext生命周期内只有一个bean实例
websocket scope: websocket生命周期内只有一个bean实例
As a rule, use the prototype scope for all stateful beans and the singleton scope for stateless beans.
singleton bean定义,eg
<bean id="accountService" class="com.foo.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default) -->
<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>
prototype bean定义 eg
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
spring容器不管理prototype bean的生命周期,可以使用bean post-processer来让容器管理prototype bean的生命周期
如果一个singleton scope的bean依赖于prototype scope的bean,因为singleton scope bean在容器初始化时就实例化,并注入需要的依赖,如果在运行时需要一个新的prototype scope bean的实例,这时候可以用spring的 method injection
request session globalSession application websocket scope只有在使用web感知的ApplicationContext(比如
XmlWebApplicationContext)
的容器才有效
如果使用setvlet2.5的web容器,并且使用DispatcherServlet以外的的处理器来处理request,需要注册org.springframework.web.context.request.RequestContextListener ServletRequestListener web.xml配置eg
<web-app>
...
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
...
</web-app>
或者
<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, and RequestContextFilter所有这些都做完全相同的事情,即将HTTP请求对象绑定到服务该请求的线程。
不同scope的bean依赖解决
spring ioc容器不仅管理这bean的初始化,而且帮你注入所需要的依赖,如果你想将一个http request scope的bean注入到一个更大范围的scope的bean,你需要借助AOP Proxy来代替这个request scope的bean。需要注入一个代理对象,该对象公开了与http request scopd bean相同的公共接口,并将方法调用委托到实际对象。eg
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- an HTTP Session-scoped bean exposed as a proxy -->
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
<!-- instructs the container to proxy the surrounding bean -->
<aop:scoped-proxy/>
</bean>
<!-- a singleton-scoped bean injected with a proxy to the above bean -->
<bean id="userService" class="com.foo.SimpleUserService">
<!-- a reference to the proxied userPreferences bean -->
<property name="userPreferences" ref="userPreferences"/>
</bean>
</beans>
默认情况下spring为标记了<aop:scoped-proxy/>的bean创建代理使用了CGLIB代理
也可以使用jdk的代理来是实现,不过只能代理接口,配置如下
<!-- DefaultUserPreferences implements the UserPreferences interface -->
<bean id="userPreferences" class="com.foo.DefaultUserPreferences" scope="session">
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
<bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
定义自己的scope
- 定义自己的scope,实现org.springframework.beans.factory.config.Scope接口
- 注册scope
Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);
或者通过xml文件注册scope
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
<bean id="bar" class="x.y.Bar" scope="thread">
<property name="name" value="Rick"/>
<aop:scoped-proxy/>
</bean>
<bean id="foo" class="x.y.Foo">
<property name="bar" ref="bar"/>
</bean>
</beans>
<bean id="..." class="..." scope="thread">