在默认情况下,Spring应用上下文中所有的bean都是以单例的形式创建的。
1.spring定义了多种作用域,可以基于这些作用域创建bean,包括
(1).单例:在整个应用中,值创建bean的一个实例。是spring默认的作用域。
(2).原型:每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean的实例。
(3).会话:在web应用中,会为每个会话创建一个bean实例。
(4).请求:在web应用中,为每个请求创建一个bean实例。
2.如果需要指定除单例外的其他作用域,需要使用@Scope注解,形式如下:
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
如果使用XML来配置的话,可以使用<bean>元素的scope属性来设置作用域。
3.使用会话和请求作用域
假设我们在淘宝购物,购物车如果是单例的,那么所有人的商品都会被添加到同一个购物车。如果是原型的,那么再其他的地方就不可以使用,所以此时我们可以考虑会话作用域。
再来了解一下ScopeProxyMode这个枚举类,具体如下显示
可以看出里面有四种选择,分别是DEFAULT,NO,INTERFACE,TARGET_CLASS。
我们再来看一下WebApplicationContext接口,如下图所示:
从上面我们可看出有多种SCOPE的作用域,而且WebApplicationContext接口继承了ApplicationContext接口,下图是ApplicationContext接口的定义:
Spring是没有办法创建基于接口的代理。它必须使用CGLib来生成基于类的代理。所以,如果bean类型是具体类的话,我们必须要将proxyMode属性设置为ScopeProxyMode.TARGET_CLASS,以此来表明要以生成目标类扩展的方式创建代理。
上面看了一下bean作用域的注解方式,接下来看看bean的作用域的xml配置方式:
(1)<bean>元素有scope属性,通过scope来配置bean的作用域。
(2)spring会为bean创建一个作用域代理,默认情况下,它会使用CGLib创建目标类的代理。也可以通过设置proxy-target-class属性设置为false,来生成基于接口的代理。使用<aop:scoped-proxy>,要使用这个元素,必须在XML的beans根元素中声明该命名空间。