Spring Bean的作用域

Spring 中的 bean 默认都是单例的,这些单例 bean 在多线程程序下如何保证线程安全呢?例如对于 Web 应用来说,Web 容器对于每个用户请求都创建一个单独的 Servlet 线程来处理请求,引入 Spring 框架之后,每个 Action 都是单例的,那么对于 Spring 托管的单例 Servlet Bean,如何保证其安全呢?Spring 的单例是基于 BeanFactory 也就是 Spring 容器的,单例 Bean 在此容器内只有一个,Java 的单例是基于 JVM,每个 JVM 内只有一个实例。

 创建一个 bean 定义,其实质是用该 bean 定义对应的类来创建真正实例的“配方”。把 bean 定义看成一个配方很有意义,它与 class 很类似,只根据一张“处方”就可以创建多个实例。不仅可以控制注入到对象中的各种依赖和配置项,还可以控制该对象的作用域。这样可以灵活选择所建对象的作用域,而不必在 Java Class 级定义作用域。Spring Framework 支持五种作用域,分别阐述如下表。

类别说明
singleton在 Spring Ioc 容器中仅存在一个 Bean 实例,Bean 以单例方式存在,默认值
prototype每次从容器中调用 Bean 时,都返回一个新的实例,即每次调用 getBean() 时,相当于执行 new XxxBean()
request每次 HTTP 请求都会创建一个新的 Bean,该作用域仅适用于 WebApplicationContext 环境
session同一个 HTTP Session 共享一个 Bean,不同 Session 使用不同 Bean,仅适用于 WebApplicationContext 环境
globalSession一般用于 Protlet 应用环境,该作用域仅适用于 WebApplicationContext 环境

 五种作用域中,request、session 和 global session 三种作用域仅在基于 web 的应用中使用(不必关心你采用的是什么 web 应用框架),只能用在基于 web 的 Spring ApplicationContext 环境。

Singleton

 当一个 bean 的作用域为 singleton,那么 Spring IoC 容器中只会存在一个共享的 bean 实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。
singleton 是单例类型,就是在创建起容器时就同时自动创建了一个 bean 的对象,不管你是否使用,它都存在了,每次获取到的对象都是同一个对象。注意,singleton 作用域是 Spring 中的缺省作用域。

  1. xml中的配置示例
    <bean id="beanScope" class="cn.csdn.service.BeanScope" scope="singleton"/>
    
  2. 注解方式配置示例
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    @Component
    @Scope(ConfigurableListableBeanFactory.SCOPE_PROTOTYPE)
    public class BeanScope {
        ......
    }
    
    或者
    @Bean
    @Scope(value = ConfigurableListableBeanFactory.SCOPE_PROTOTYPE)
    public BeanScope beanScope(){
        ......
    }
    

Prototype

 当一个 bean 的作用域为 Prototype,表示一个 bean 定义对用多个对象实例。Prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean()) 时都会创建一个新的 bean 实例。
 Prototype 是原型类型,它在我们创建容器的时候并没实例化,而是当我们获取 bean 的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。

  1. xml中的配置示例
    <bean id="beanScope" class="cn.csdn.service.BeanScope" scope="prototype"/>  
    或者
    <bean id="beanScope" class="cn.csdn.service.BeanScope" singleton="false"/> 
    
  2. 注解方式配置示例
    @Bean
    @Scope(value = ConfigurableListableBeanFactory.SCOPE_PROTOTYPE)
    public BeanScope beanScope(){
        ......
    }
    

Request

 当一个bean的作用域为 Request,表示在一次 HTTP 请求中,一个 bean 定义对应一个实例;即每个 HTTP 请求都会有各自的 bean 实例,它们依据某个 bean 定义创建而成。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。

  1. xml中的配置示例
    如果你使用的是 Servlet 2.4 及以上的 web 容器,那么你仅需要在 web 应用的 XML 声明文件 web.xml 中增加下述 ContextListener 即可:
    <web-app>
        ...
         <listener>
            <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
        </listener>
        ...
    </web-app>
    
    <bean id="beanScope" class="cn.csdn.service.BeanScope" scope="request"/>  
    
  2. 注解方式配置示例
    @Bean
    @Scope(value = "request")
    public BeanScope beanScope(){
        ......
    }
    

 针对每次 HTTP 请求,Spring 容器会根据 loginAction bean 的定义创建一个全新的 LoginAction bean 实例,且该 loginAction bean 实例仅在当前 HTTP request 内有效,因此可以根据需要放心的更改所建实例的内部状态,而其他请求中根据 loginAction bean 定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,request 作用域的 bean 实例将被销毁。

Session

 当一个 bean 的作用域为 Session,表示在一个 HTTP Session 中,一个 bean 定义对应一个实例。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。

  1. xml中的配置示例
    <bean id="beanScope" class="cn.csdn.service.BeanScope" scope="session"/>  
    
  2. 注解方式配置示例
    @Bean
    @Scope(value = "session")
    public BeanScope beanScope(){
        ......
    }
    

 针对某个 HTTP Session,Spring 容器会根据 userPreferences bean 定义创建一个全新的 userPreferences bean 实例,且该 userPreferences bean 仅在当前 HTTP Session 内有效。与 request 作用域一样,可以根据需要放心的更改所创建实例的内部状态,而别的 HTTP Session 中根据 userPreferences 创建的实例,将不会看到这些特定于某个 HTTP Session 的状态变化。当 HTTP Session 最终被废弃的时候,在该 HTTP Session 作用域内的 bean 也会被废弃掉。

Global Session

 当一个 bean 的作用域为 Global Session,表示在一个全局的 HTTP Session 中,一个 bean 定义对应一个实例。典型情况下,仅在使用 portlet context 的时候有效。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。

  1. xml中的配置示例
    <bean id="beanScope" class="cn.csdn.service.BeanScope" scope="globalSession"/>  
    
  2. 注解方式配置示例
    @Bean
    @Scope(value = "globalSession")
    public BeanScope beanScope(){
        ......
    }
    

 global session 作用域类似于标准的 HTTP Session 作用域,不过仅仅在基于 portlet 的 web 应用中才有意义。Portlet 规范定义了全局 Session 的概念,它被所有构成某个 portlet web 应用的各种不同的 portlet 所共享。在 global session 作用域中定义的 bean 被限定于全局 portlet Session 的生命周期范围内。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值