• 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 实战 (第四版)》

  • 相关阅读:
    ural 1080 Map Coloring DFS染色
    hdu 4287 Intelligent IME
    hdu 4268 Alice and Bob 区域赛 1002 (STL、SBT实现)
    SBT专题训练
    hdu 4276 The Ghost Blows Light 区域网络赛 1010 树上背包+spfa
    hdu 4278 Faulty Odometer
    hdu 4279 Number
    VIM 插件(转)
    Linux环境变量的设置(转)
    福昕PDF阅读器 v3.3 破解
  • 原文地址:https://www.cnblogs.com/shirui/p/9520654.html
Copyright © 2020-2023  润新知