Spring实战学习笔记——bean的作用域

来源:互联网 发布:什么软件小额贷款成功 编辑:程序博客网 时间:2024/05/17 20:00

bean的作用域

  在默认情况下,Spring应用上下文中所有的bean都是以单例(singleton)的形式创建的。无论一个给定的bean被注入多少次,每次所注入的实例都是同一个实例。
  在大多数情况下,单例bean是很理想的。但是如果使用的类是易变的(mutable),他们自身会有一些特定的状态,在这种情况下重用bean变得既不安全,由此看来此时单例bean就不再是什么好主意了。Spring提供了多中作用域,可以基于这些作用域创建bean,包括:

  • 单例(Singleton):在整个应用中,只创建bean的一个实例。
  • 原型(Prototype):每次注册如或者通过Spring上下文获取的时候,都会创建一个新的bean实例。
  • 会话(Session):在Web应用中,为每个会话创建一个bean实例。
  • 请求(Request):在Web应用中,为每个请求创建一个bean实例。
      默认情况下创建的bean的作用域是单例的,但是对于易变的类型并不合适,如果使用其他的的作用域需要使用@Scope注解,它可以与@Compoent@Bean一起使用。例如:
@Component@Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)public class Notepad {……}

  这里使用了ConfigurableBeanFactory类的SCOPE_PROTOTYPE常量设置了原型作用域。当然也可以使用@Scope("prototype"),但是使用SCOPE_PROTOTYPE常量更加安全并且不易出错。如果想要在Java配置将Notepad声明为bean,可以使用@Scope@Bean来指定所需的作用域。如果使用XML来配置bean的话,可以使用<bean>元素的scope属性来设置作用域:
这里写图片描述
  无论是用那种方式来声明原型作用域,每次注入或从Spring应用上下文中检索该bean的时候,都会创建自己的实例。

使用会话和请求作用域
  在Web应用中,如果能够实例化在会话和请求范围内共享的bean,那将是非常有价值的事情。
  会话作用域可以给用户以最大的关联性,在一个会话中都持有同一个相同的bean。例如在电子商务应用中,用户在购物过程中应该都持有属于自己的唯一的一个购物车,在这个场景下,使用会话作用域是最合适不过的了。使用@Scope注解。

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

  在这里我们将value的值设置为了WebApplicationContext中的SCOPE_SESSION常量(它的值是session)。这会告诉Spring为Web应用中的每个会话创建一个ShoppingCart实例。这样会创建多个ShppoingCart bean的实例,但是对于给定的会话只会创建一个实例,在当前会话的相关的操作中,这个bean实际上相当于是单例的。
  通过上面的分析,了解到系统中将有多个ShoppingCart实例,我们并不想让Spring将某个固定的ShoppingCart实例注入进去。希望当用户使用购物车功能的时候,所使用的ShoppingCart恰好是当前会话所对应的哪一个。
  实际上,Spring在处理bean的时候,并不会将实际的bean注入到相应的位置,Spring会注入到一个ShoppingCart bean的代理。如下图所示:
       这里写图片描述
  图中的代理会暴露于ShoppingCart相同的方法,当其他类调用其中的方法的时候,代理会对其进行懒解析将其委托给作用域中真正的bean。
  这里需要对proxyMode属性进行说明:如果此时ShoppingCart 为一个接口,则需要使用ScopedProxyMode.INTERFACES(这也是最理想的代理模式)。但是如果其作用的为一个具体的类,Spring就无法创建基于接口的代理,需要将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS,以便生成目标扩展的方式创建代理。请求作用域的bean与会话作用域bean面临相同的问题,所以同样需要一作用域代理的方式进行注入。

在XML中声明作用域代理
  如果使用XML来声明会话或请求作用域的bean,可以利用<bean>元素的scope属性设置作用域,并且需要使用Spring aop命名空间的一个新元素。它会告诉Spring为bean创建爱你一个作用域代理,且默认情况下会使用CGLib创建目标类的代理。但可以将proxy-target-class属性设置为false,进而要求它生成基于接口的代理。例如:
这里写图片描述

阅读全文
0 0
原创粉丝点击