【发布时间】:2014-03-05 15:05:06
【问题描述】:
我的问题是: 假设我有一个spring bean:一个DAO(当然它是一个单例)
那么,当我们有很多用户想要同时使用这个 bean 时:会发生什么?
或者,
为每个用户,spring 为他实例化一个 DAO bean?
==> 我们有一个应用程序上下文的单例:spring 是否为每个用户创建了一个上下文?
【问题讨论】:
标签: spring singleton applicationcontext
我的问题是: 假设我有一个spring bean:一个DAO(当然它是一个单例)
那么,当我们有很多用户想要同时使用这个 bean 时:会发生什么?
或者,
为每个用户,spring 为他实例化一个 DAO bean?
==> 我们有一个应用程序上下文的单例:spring 是否为每个用户创建了一个上下文?
【问题讨论】:
标签: spring singleton applicationcontext
(当然是单例)
那么它就是一个单例。 ApplicationContext 只会创建一个实例并将同一个实例传递到任何需要它的地方。
为每个用户创建一个 [实例化] DAO bean 给他?
不,它会检索并给他们相同的DAO 实例。
==> 我们有一个应用程序上下文的单例:spring 是否为每个用户创建了一个上下文?
我不太确定您对每个用户的意思。 Java 应用程序不了解用户。如果您的意思是在多线程应用程序的上下文中,它仍然无关紧要。注入的DAO bean 仍将是那个单一实例。
如 cmets 中所述,您有责任处理 DAO 的状态,如果它是可变的,则处理并发访问。使用数据源处理事务(可能使用@Transactional)。
【讨论】:
您不使用 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。
【讨论】: