Spring_总结_04_高级配置(四)_bean的作用域

一、前言

本文承接上一节:Spring_总结_04_高级配置(三)之处理歧义

1.单例bean

Spring应用上下文中所有的bean默认都是单例的。也就是说,不管一个bean被注入到其他bean多少次,每次注入的都是同一个实例。

2.有状态bean与无状态bean

单例bean适用于那些无状态的对象,在多数情况下,单例bean是很理想的方案。但是有时候,你所使用的类是易变的,他会保持一些状态(有状态),因此重用是不安全的。

 

举个例子:

      这段时间在做一个脚本引擎,需要在java中执行js代码。当我在程序中注入一个单例的脚本引擎,并用这个脚本引擎去重复执行一段js代码。

      第一次执行的时候,能正常执行;第二次执行的时候,却报js中定义的一个对象已存在。

      这就是因为在第二次执行的时候,单例的脚本引擎中已经包含了第一次执行时的状态,即第一次执行之后,js中的对象已存在于脚本引擎中,因此导致第二次执行时出现重复定义的错误。

在这个例子中,我们需要的其实是,每次执行的时候单独为我创建一个bean,而不是每次使用的都是同一个bean。

 

二、bean的作用域

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

 

1 单例(Singleton) 在整个应用中,只创建bean的一个实例
2 原型(Prototype) 每次注入或者通过Spring应用上下文获取的时候,都会一个新的bean实例。
3 会话(Session) 在Web应用中,为每个会话创建一个bean实例
4 请求(Request) 在Web应用中,为每个请求创建一个bean实例

 

单例是默认的作用域,这对于易变类型,并不合适,这是就要为bean声明一个@Scope注解,可配合@Component或@Bean一起使用。

 

1.Prototype

为bean声明如下注解,即可创建原型bean

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

或者

@Scope("prototype")

 

示例如下:

(1)自动装配时

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad{...}

 

(2) Java 配置时

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Notepad notepad(){
    return new Notepad();
}

 

(3) xml 配置

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

 

2.Session

为bean声明如下注解,即可创建会话bean

@Component
@Scope(value=WebApplicationContext.SCOPE_SESSION,
             proxyMode=ScopedProxyMode.TARGET_CLASS)
public ShoppingCart cart(){...}

假设,我们要将ShoppingCart bean 注入到单例 StoreService bean的 Setter方法中,如下所示:

@Coponent
public class StoreService{

     @Autowired
     public void setShoppingCart( ShoppingCart shoppingCart){
           this.shoppingCart = shoppingCart;
     }

}

  因为storeService是一个单例bean,会在Spring应用上下文加载的时候创建。当它创建的时候,Spring会注入一个到ShoppingCart的代理。当StoreService调用ShoppingCart的方法时,代理会对其进行懒解析并将调用委托给会话作用域内真正的ShoppingCart bean。  

  注意到proxyMode属性,ScopedProxyMode.TARGET_CLASS 表明将创建一个基于目标类的代理。

而若ShoppingCart是一个接口时,则需要使用 ScopedProxyMode.INTERFACES,表明要创建一个实现ShoppingCart接口的代理,并将调用委托给实现bean。

 

3.Request

为bean声明如下注解,即可创建请求bean

@Component
@Scope(value=WebApplicationContext.SCOPE_REQUEST,
             proxyMode=ScopedProxyMode.TARGET_CLASS)
public ShoppingCart cart(){...}

 

三、参考资料

1.《Spring 实战 (第四版)》

 

posted @ 2018-08-22 21:54  shirayner  阅读(301)  评论(0编辑  收藏  举报