spring bean scope

本文介绍了Spring框架中Bean的多种作用域,包括Singleton、Prototype、Request、Session、GlobalSession、Application、WebSocket等,并探讨了不同作用域的适用场景和生命周期管理。对于Singleton Bean依赖于Prototype Bean的情况,文章提到了使用Spring的Method Injection和AOP代理来解决。同时,还讨论了如何在Web环境中配置和使用这些作用域,以及如何自定义新的作用域。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

                                 spring bean scope

spring bean scope有如下几种取值

scope描述
singleton(Default) Scopes a single bean definition to a single object instance per Spring IoC container.
prototypeScopes a single bean definition to any number of object instances.
requestScopes 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.
sessionScopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
globalSessionScopes 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.
applicationScopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocketScopes 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

  1. 定义自己的scope,实现org.springframework.beans.factory.config.Scope接口
  2. 注册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">

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值