一 、bean的作用域
单例(singleton):整个应用中,只创建一个bean的实例 (默认)
原型(prototype):每次注入或者通过spring上下文获取的时候,都会创建一个新的bean实例。
会话(session):在Web应用中,为每次会话创建一个新的bean实例。
请求(request):在Web应用中,为每次请求创建要给新的bean实例。
默认是singleton,如果需要使用其他作用域,可以使用 @scope注解:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) //推荐 安全不易出错
//@Scope("prototype")
public class Notepad {
}
也可以使用xml配置
<bean id="notepad"
class="com.beanConfig.beanScope.Notepad"
scope="prototype">
</bean>
会话和请求作用域
例如,在电子商务应用中,有一个代表购物车的bean,如果是单例的话,那么将会导致所有的用户都会向一个购物车里添加商品。如果是原型的话,那么在应用中一个地方添加商品,在另一个地方就不能用了。
会话作用域是最合适的。
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.INTERFACES)
public interface ShopingCart {
}
SCOPE_SESSION会告诉spring我为Web每个会话创建一个bean。在当前会话中这个bean其实是单例的。
proxyMode属性
@Component
public class StoreService {
private ShopingCart shopingCart;
@Autowired
public void setShopingCart(ShopingCart shopingCart) {
this.shopingCart = shopingCart;
}
}
StoreService是一个单例bean,会在spring上下文加载的时候创建。而shopingCart 是会话作用域。在StoreService加载的时候,shopingCart还不存在。只有某个用户进入系统才会出现。
而且,当系统中有多个shopingCart实例的时候,我们只希望自己会话中的shopingCart实例注入到StoreService中。
怎么解决的呢?
spring不会将实际的shopingCart注入进去,而是会注入一个shopingCart bean代理。这个代理暴露域shopingCart相同的方法。当进行方法调用时,代理会进行懒解析,并将调用委托给会话作用域中真正的shopingCart bean。
那么proxyMode属性
ScopedProxyMode.INTERFACES表明代理要通过接口实现。ScopedProxyMode.TARGET_CLASS基于类的代理。
在xml中声明作用域
<bean id="cart" class="com.beanConfig.beanScope.ShopingCart" scope="session">
<aop:scoped-proxy proxy-target-class="false"/>
</bean>
默认时CGLib创建目标类代理。proxy-target-class=“false” 基于接口创建代理