spring bean的会话和请求作用域

bean生命周期

spring bean默认装配生成对象是采用单例形式,只创建一个对象,这种形式,当需要保存对象状态时候存在一定问题,多处共用该对象会造成对象污染,srping bean还有原型、会话、请求等其他几种对象生成方式。

  • 单例:在整个web应用中,只产生bean的一个实例。
  • 原型:在每次注入或者在应用上下文中获取bean时候都产生一个bean的实例。
  • 会话:在应用的一次会话中产生一个bean的实例。
  • 请求:在应用的一次请求中产生一个bean的实例。

会话和请求的作用域

在web应用中如果能够在指定会话或者请求作用域内创建一个bean的实例将是非常有意思的,例如在电子商务购物就是一个典型场景,如果用一个bean代表购物车,那么将出现所有人都往一个购物车添加商品的情况出现,如果采用原型方式,那么如果一个用户往购物车添加物品,在应用的另外一个场景可能看不到该信息。

这时候采用会话作用域最为合适,可以用@scope注解进行设定。

通过指定scope的值scope_session只在当前会话中创建一个bean的实例,该实例的生命周期只存在于当前会话中。
@scope还有另外一个属性叫做proxyMode,该属性解决了会话作用域bean注入到一个单例bean中的问题。
我们看一下如下实例:

我们将会话作用域的ShoppingCart注入到单例的StoreService中,StoreService在应用上下文中创建时候需要引用ShoppingCart,这时候该实例还没有创建,需要在用户登录之后产生购物车会话之后才能创建,另外系统中会产生多个ShoppingCart实例,StoreService不需要固定指定某个ShoppingCart实例,需要在StoreService调用购物车时候引用当前登录用户的ShoppingCart实例。

ShoppingCart并不会实际注入到StoreService中,spring会将ShoppingCart的代理注入到StoreService中,当StoreService调用ShoppingCart的方法时首先调用的是代理,代理通过懒解析在调用真实的会话中的ShoppingCart方法。

代理分为两种情况,如果ShoppingCart是接口,proxyMode属性值需要设置为ScopeproxyMode.Interfaces,代表该代理代理的是一个接口,如果ShoppingCart是一个具体的实现类,proxyMode的属性值需要设置为ScopeproxyMode.Target_class,此时spring需要通过CCglib生成该类的代理。

你可能感兴趣的:(架构,java架构)