Spring bean的作用域

spring中的四种作用域

  1. 单例(singleton):在整个应用中,只创建一个bean的实例
  2. 原型(prototype):每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean实例
  3. 会话(session):每个会话创建一个bean的实例
  4. 请求(request):每个请求创建一个bean的实例
    默认的作用域是单例,如果选择其他作用域,可以在bean声明的地方添加@Scope注解或者在<bena>标签设置scope属性。
    @Scope注解的value属性推荐使用ConfigurableBeanFactory类中的常量,如果是web应用则使用WebApplicationContext中定义的常量。

会话作用域

以电子商城的购物车为例,如果将其设置为单例,则所有用户都使用同一个购物车对象,如果将其设置为原型,则一个用户可能会使用多个购物车对象,请求也是如此,这些都是不合理的,应该为购物车使用会话作用域。

代码清单
@Bean
@Scope(
  value = WebApplicationContext.SCOPE_SESSION,
  proxyMode = ScopedProxyMode.INTERFACES)
public ShoppingCart cart(){···}

value = WebApplicationContext.SCOPE_SESSION设置了购物车bean的作用域为session,表示为web应用中每个session创建一个购物车对象,这个购物车对象在session作用域中是单例的。
proxyMode = ScopedProxyMode.INTERFACES设置了购物车bean的代理模式为基于接口的。解决了将session和request作用域的bean注入到一个singleton作用域bean的问题。
假设这里有一个singleton作用域的StoreService bean。

@Component
public class StoreService{
  @Autowired
  private ShoppingCart cart;
}

由于StoreService是singleton作用域的bean,所以会在spring应用上下文加载的时候创建,而ShoppingCart是session作用域的,只有当用户发起请求才会创建。且可能会有多个购物车实例被创建,不应该为StoreService注入一个固定的ShoppingCart。
此时为购物车设置的proxyMode属性就发挥了作用,spring并不会把某个ShoppingCart实例注入到StoreService,而是注入到一个ShoppingCart的代理,这个代理暴露和ShoppingCart接口中相同的方法,此时StoreService以为这个代理就是一个ShoppingCart,而当StoreService调用ShoppingCart方法的时候,代理将调用委托给session作用域中真正的ShoppingCart实例处理。
但是当bean不是一个接口,而是某个具体类的时候,ScopedProxyMode.INTERFACES不能创建基于具体类的代理,此时必须使用CGLib来生成基于具体类的代理,通过将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS来表明要以生成目标类扩展的方式创建代理。
request作用域的bean也同样应该以作用域代理的方式实现注入。

在XML中声明作用域代理

通过设置在<bean>标签中的scope属性,可以指定bean的作用域。 但是设置代理模式,必须要用aop命名空间的元素<aop:scope-proxy />。默认是使用CGLib创建目标类的代理,可以通过将proxy-target-class属性设置为false实现创建基于接口的代理<aop:scope-proxy proxy-target-class="false" />

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值