一、默认情况下,spring应用上下文中所有bean都是作为以单例的形式创建的。
spring定义了多种作用域,可以基于这些作用域创建bean
1.单例(singleton):在整个应用中,之创建bean的一个实例
2.原型(prototype):每次注入或者通过spring应用上下文获取的时候,都会创建一个新的bean实例。
3.会话(session):在web应用中,为每个会话创建一个bean实例
4.请求(request):在web应用中,为每个请求创建一个bean实例
eg: 注解
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DemoService(){
...
}
eg: xml
<bean id="demoService" class="com.pz.demo.DemoServiceImpl" scope="prototype"/>
二、使用会话和请求作用域注意点
会话和请求作用域的bean不会随系统的启动而创建对应的实例,而是等到用户请求的时候才会创建。这就导致了这两个作用域的bean注入到单例出现问题,需要为@Scope注解添加属性proxyMode。
eg:注解
@Component
@Scope(ConfigurableBeanFactory.SCOPE_SESSION, proxyMode=ScopedProxyMode.INTERFACES)
public class DemoService(){
...
}
如果DemoService是接口实现类,spring可以创建基于借口的代理实现;如果是一个具体的类,spring就无法创建他的代理实现,必须使用CGLib来生成基于类的代理,所以必须将proxyMode属性设置为ScopedProxyMode.TARGET_CLASS,以此表明要生成目标类扩展的方式创建代理。
eg:xml
<!-- 默认为CGLib实现 -->
<bean id="demoService" class="com.pz.demo.DemoServiceImpl" scope="session">
<aop:scoped-proxy/>
</bean>
<!-- 添加proxy-target-class属性设置为接口代理 -->
<bean id="demoService" class="com.pz.demo.DemoServiceImpl" scope="session">
<aop:scoped-proxy proxy-target-class="false"/>
</bean>