Bean 作用域

Spring定义了多种作用域,可以基于这些作用域创建bean

Singleton  单例   整个应用中,只创建一个

Prototype  原型   每次注入或者通过Spring上下文获取时,都会创建一个新的bean实例

Session    会话    在web应用中,为每个会话创建一个bean实例

Request    请求     在web应用中,为每个请求创建一个bean实例

单例是默认的作用域。可以通过@Scope注解来改变,它可以和@Bean和@Component一起使用。

@Component

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

public   class  Notepad {   .....   }

同样,可以使用XML来配置bean的话,则:

<bean   id =  "notepad"   class = "com.myapp.Notepad"   scope = "prototype" />

扫描二维码关注公众号,回复: 6515142 查看本文章

这样,每次注入或者从Spring上下文获取bean都会创建新的实例

会话作用域和请求作用域

如电子商务系统中,一个bean代表一个购物车,那么如果是单例的话,所有的用户都向一个购物车添加,如果是原型(多例)作用域的话,在一个地方添加购物车,另一个地方就不能用了。就购物车而言,会话作用域最为合适。因为它与给定用于关联性最大。

@Component

@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.INTERFACES)

public  ShoppingCart  cart()  {   ...........    } 

这里,将value设置成WebApplicationContext中的SCOPE_SESSION常量,它会告诉Spring为每个会话创建一个实例bean

@Scope还有一个属性 proxyMode,它被设置成ScopedProxyMode.INTERFACES,这个属性解决了将会话或者请求作用域的bean注入到单例bean中所遇到的问题。如:

@Component

public   class    StoreService{

   @Autowired

     public   void   setShoppingCart(ShoppingCart   shoppingCart){

           this.shoppingCart  = shoppingCart;

   }

....

}

因为StroeService是一个单例bean,会在Spring上下文加载的时候创建它,当它创建的时候,Spring会试图将ShoppingCart  bean注入到setShoppingCart()方法中,但是ShoppingCart bean是会话作用域的,此时并不存在,直到某个用户进入系统,创建会话后才会出现ShoppingCar 实例。Spring并不会将实际的ShoppingCart bean注入到StoreServeice中,Spring会注入一个到Shopping cart Bean的代理,这个代理会暴露与ShoppingCart相同的方法,所以Service会认为他是一个购物车。但是当StoreService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean.

proxyMode属性被设置成ScopedProxyMode.INTERFACES,表明这个代理要实现ShoppingCart接口,并将调用委托给实现bean.如果ShoppingCart是一个接口,那么这么设置是可以的。但是如果ShoppingCart是一个具体的类的话,Spring就没有办法创建基于接口的代理了。此时,它必须使用CGLib来生成基于类的代理,所以,如果bean类型是具体类的话,我们必须将proxyMode属性设置成:ScopedProxyMode.TARGET_CLASS,以此来表明要生成目标类扩展的方式创建代理。请求作用域的bean也会面临同样的装配问题,因此请求作用域的bean应该也以作用域代理的方式进行注入。

      

在XML中声明作用域代理

<bean  id="cart"  class = "com.myapp.ShoppingCart"   >

  <aop:scopde-proxy / >

</bean>

  <aop:scopde-proxy / >是与@Scope注解的proxyMode属性功能相同的Spring XML配置元素,它会告诉Spring为bean创建一个作用域代理,默认情况下,它会使用CGLib创建目标类的代理,但是我们可以将proxy-target-class属性设置为false,进而要求它生成基于接口的代理。

<bean  id="cart"  class = "com.myapp.ShoppingCart"  scope="session" >

  <aop:scopde-proxy   proxy-target-class="false"/ >

</bean>

 

猜你喜欢

转载自blog.csdn.net/m0_37668842/article/details/82754979