【Spring】3.4、bean的作用域

默认情况下,bean是单例的形式创建的,既整个应用程序使用的bean是同一个实例。

有些情况,如果想重用这个bean,结果这个bean被之前的操作污染了,会使程序发生错误。

Spring支持为bean设置作用域,提供了以下几种作用域:

单例(Singleton):整个应用中,只创建bean的一个实例。

原型(Prototype):每次注入或者通过Spring应用上下文获取的时候,都会创建一个新的bean实例。

会话(Session):Web应用中,为每个会话创建一个bean实例。

请求(Request):Web应用中,为每个请求创建一个bean实例。

//可以使用组件扫描时,声明作用域;作用域可以使用ConfigurableBeanFactory表示
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Cake implements Dessert{...}

//可以在Java配置Bean时,声明作用域;作用域也可以使用字符串表示,不过建议使用ConfigurableBeanFactory更不容易出错
@Bean
@Scope("prototype")
public Dessert iceCream{
    return new IceCream();
}
<!-- 使用XML配置时,设置bean作用域 -->
<bean id="iceCream" class="com.desserteater.IceCream" scope="prototype" />

使用会话和请求作用域

 某些情景下,某个bean(例如Web应用中的购物车bean),不应该是对于程序单例的,而是对于每一个用户有对应一个bean。

这种情况下,适合使用会话作用域的bean

@Component
@Scope(
    value=WebApplicationContext.SCOPE_SESSION,
    proxyMode=ScopedProxyMode.INTERFACES)
public ShopingCart cart(){...}

WebApplicationContext:SCOPE_SESSION属性表明Spring为每一个Web会话创建一个实例

ScopedProxyMode:解决会话作用域的bean注入到单例bean的问题。当会话作用域的bean注入到单例bean的时候,Spring改为注入一个bean代理,当单例bean需要调用会话作用域的bean时,该代理才针对当前会话,找到对应的bean,进行调用。

ScopedProxyMode.INTERFACES:当该bean是一个接口的时候,设置值为INTERFACES,表示该代理要实现该接口,并讲调用委托给实现的bean。

ScopedProxyMode.TARGET_CLASS:当该bean是一个类的时候,设置值为TARGET_CLASS,因为SPring无法创建基于接口的代理,需要使用CGLib来生成基于类的代理,通过生成目标类扩展的方式来进行代理。

同样,请求作用域也是有一样的问题,同样处理即可。

在XML中声明作用域代理

引用aop命名空间

<?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/aop
      http://www.springframework.org/schema/aop/spring-beans.xsd
      http://www.springframework.org/schema/beans 
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/context">

    <!-- 配置内容 -->

</beans>

使用aop命名控件声明作用域代理:

<aop:scoped-proxy />是和@Scope注解的proxyMode属性相同的XML元素

它告诉Spring为bean创建一个作用域代理,默认状态下,会使用CGLib创建目标类代理。

<bean id="cart"
    class="com.myapp.ShoppingCart"
    scope="session">
    <aop:scoped-proxy />
</bean>

 

设置为生成基于接口的代理

<bean id="cart"
    class="com.myapp.ShoppingCart"
    scope="session">
    <aop:scoped-proxy proxy-target-class="false" />
</bean>

 

posted @ 2018-05-09 16:54  LiveYourLife  阅读(314)  评论(0)    收藏  举报