通过工厂方法创建Spring Bean和违反Singleton模式

时间:2013-05-31 09:48:43

标签: multithreading spring thread-safety race-condition

朋友们,我正在阅读Spring 3 in Action

它说: - 当我们使用Constructors创建它们时,Spring Containers默认提供Singleton Bean。但是如果我们使用工厂方法,那么它应该以只返回单个bean的方式实现。带标题的页码37

CREATING BEANS THROUGH FACTORY METHODS

因此,作者必须通过遵循代码来保持线程安全。否则,两个并发线程可能会创建两个Spring Bean实例。

 package com.springinaction.springidol;
  public class Stage {

      private Stage() {
            }

     private static class StageSingletonHolder {

         static Stage instance = new Stage();
              }

       public static Stage getInstance() {
         return StageSingletonHolder.instance;
                }

     }

静态getInstance()方法每次调用时都返回相同的实例。 (对于线程 安全性,getInstance()采用一种称为“按需初始化持有者”的技术来创建单例实例。)

然后它使用XML

      <bean id="theStage"
        class="com.springinaction.springidol.Stage"
          factory-method="getInstance" />

将getInstance声明为工厂方法。

我明白了。但是,出于好奇,我想如果我通过删除这个静态初始化从Class Stage中删除这个线程安全的概念

    package com.springinaction.springidol;
       public class Stage {
       private Stage() {
               }

              public static Stage getInstance() {
               return new Stage();
                 }
          }

然后可以通过两个同时线程来拥有多个Stage类的实例。我知道这只是一种可能性。在这种情况下,当线程1在Spring Container(ApplicationContext)实例上调用getBean(“theStage”)方法时,就有可能。它发现没有这种bean的实例。在线程2接管的同时它也发现没有这种bean的实例。现在两个线程都创建了两个不同的Spring bean,因为工厂方法不是线程安全的。

如果两个线程通过修改的getInstance方法(现在不是线程安全的)返回不同的实例,这种可能性如何增加呢。

请帮助

1 个答案:

答案 0 :(得分:0)

  

如何增加两个线程返回的可能性   通过修改的getInstance方法的不同实例(不是   现在线程安全)

这种情况唯一的情况是bean是否使用延迟加载。否则spring会在启动时创建bean,每当你的线程请求一个Stage实例时,Spring将返回它已经拥有的那个。

我还没读过这本书,但我想作者正在使用StageSingletonHolder 100%确定bean在当前的类加载器中永远不会有另一个实例。然而,单例是java中的一个谎言,因为你可以拥有多个类加载器,因此可以有多个单例。

这篇非常好的文章解释了这一点:http://tech.puredanger.com/2007/07/03/pattern-hate-singleton/