1、单例(Singleton):在整个应用中只创建bean的一个实例,是默认的作用域;
2、原型(Prototype):每次注入或者通过Spring应用上下文获取时都会创建一个新的bean实例;
也可以使用@Scope("prototype"),但是使用SCOPE_PROTOTYPE常量更加安全
3、会话(Session):在web应用中,为每个会话创建一个bean实例;
在web应用中,如果能够实例化在会话和请求范围内共享的bean,是很有价值的,比如电子商务应用中,可能会有一个bean代表用户的购物车。如果购物车是单例,那将会导致所有的用户都会向同一个购物车中添加商品,如果购物车是原型作用域,那么在应用中某一个地方往购物车中添加商品,在应用中的另一个地方就不可用了
为什么要加proxyMode=ScopedProxyMode.INTERFACES属性呢?如下图所示:
Storeservice是一个单例的bean,会在Spring应用上下文加载的时候创建,当它创建的时候Spring会试图将ShoppingCart bean注入到setShoppingCart()方法中,但是ShoppingCart bean是会话作用域的,此时并不存在,直到某个用户进入系统,创建了会话之后才会出现ShoppingCart的实例。而且系统中将会有多个ShoppingCart实例,因为每个用户一个,我们并不想让Spring注入某个固定的ShoppingCart实例到Storeservice中,我们希望处理业务时使用的实例刚好是当前会话对应的那一个。Spring并不会将实际的ShoppingCart bean注入到StoreService中,Spring实际会注入一个ShoppingCart bean的代理,这个代理会暴露与ShoppingCart相同的方法,当StoreService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean。
ProxyMode属性被设置成ScopedProxyMode.INTERFACES代表这个代理要实现一个接口,并将调用委托给实现bean。如果bean类型是具体类,则ProxyMode属性设置为ScopedProxyMode.TARGET_CLASS。
如果是xml配置,则设置为:
使用aop设置为代理模式,<aop:scoped-proxy>和@Scoped注解的ProxyMode属性功能相同,默认情况下会使用CGlib创建目标类的代理,如果要求生成基于接口的代理,则将proxy-target-class属性设为false:
4、请求(Request):在web应用中,为每个请求创建一个bean实例。