【问题标题】:Spring Singleton and concurrent accessSpring Singleton 和并发访问
【发布时间】:2014-03-05 15:05:06
【问题描述】:

我的问题是: 假设我有一个spring bean:一个DAO(当然它是一个单例)

那么,当我们有很多用户想要同时使用这个 bean 时:会发生什么?

或者,

为每个用户,spring 为他实例化一个 DAO bean?

==> 我们有一个应用程序上下文的单例:spring 是否为每个用户创建了一个上下文?

【问题讨论】:

    标签: spring singleton applicationcontext


    【解决方案1】:

    (当然是单例)

    那么它就是一个单例。 ApplicationContext 只会创建一个实例并将同一个实例传递到任何需要它的地方。

    为每个用户创建一个 [实例化] DAO bean 给他?

    不,它会检索并给他们相同的DAO 实例。

    ==> 我们有一个应用程序上下文的单例:spring 是否为每个用户创建了一个上下文?

    我不太确定您对每个用户的意思。 Java 应用程序不了解用户。如果您的意思是在多线程应用程序的上下文中,它仍然无关紧要。注入的DAO bean 仍将是那个单一实例。

    如 cmets 中所述,您有责任处理 DAO 的状态,如果它是可变的,则处理并发访问。使用数据源处理事务(可能使用@Transactional)。

    【讨论】:

    • 完全同意这个答案。我要补充一点,您必须在 DAO 中管理事务以处理对单例实例的多次使用。
    • @Sotirios Delimanolis:感谢您的回复:)。你说>(处理你的DAO的状态是你的责任):这不是spring容器的作用吗?
    • @zied.j 不,Spring 将为 DAO 管理 bean 的生命周期。它对类的内部情况一无所知。如果需要,您可以确保它是线程安全的。
    【解决方案2】:

    您不使用 DAO 作为 Spring bean。 Spring bean(单例范围)更像是一种服务。

    假设你有一个 Pizza Dao 和一个 PizzaService,你的 Service 是 spring bean,而 Pizza 不是。

    class Pizza {
        Set ingredients = ... ; 
    
        public Pizza(Set s) {
             ...
        }
    
        private addIngredient(Object o ) {
            set.add... 
        }
    }
    
    @Service
    class PizzaService {
        private Pizza createPizza(..){
            Pizza p = new Pizza(); 
            ....
            return pizza;
        }
    
        private void persistPizza(Pizza pizza){
            ..save to db..
        }
    } 
    

    测试你的服务:

    class JunitFoo{
        @Autowired private PizzaService service; 
    
        @Test
        someMethod(){
            Pizza p = service.createPizza(); 
            p.addIngredient(cheese)
            service.persistPizza(p);
        }
    }
    

    您还可以在 JunitFoo 中实现 Runnable 并使用不同的线程(您的用户)多次启动 someMethod,每个用户都会得到自己的 Pizza。 但所有用户都使用相同的 PizzaService

    由于这个原因,单例是 Spring bean 的默认范围。您还可以通过从应用程序上下文中获取披萨来创建披萨,但在这种情况下,您需要原型,否则所有用户都共享同一个披萨

    <bean id="pizza" class="foo.Pizza" scope="prototype" > 
    <default set of pizza stuff> 
    </bean>
    

    如果您这样做,您的 PizzaService 可能如下所示:

    @Service
    class PizzaService {
        @Autowired private ApplicationContext context;
        private Pizza createPizza(..){
            return (Pizza) context.getBean("pizza");
        }
    
        private void persistPizza(Pizza pizza){
            ..save to db..
        }
    } 
    

    这个主题在一篇文章中涵盖它的方式很大,我希望我能帮助你并提高你的理解。 Please also check the spring documantation about bean scopes

    【讨论】:

      猜你喜欢
      • 2011-11-29
      • 2020-03-16
      • 1970-01-01
      • 2011-06-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多