1

假设以下类是单例

public class myDAO {
    //determines the tableName and Id column names to based on itemType
    private String itemType;
    public void setItemType(String itemType) {...} 

    //Following methods use itemType to customize their queries
    public boolean findObj(int id){...} 
    public boolean deleteObj(int id){...}
    public boolean updateObj(Obj obj){...}
    //etc...
}

该代码最近使用 setter 进行了重构,从而为 DAO 提供了一些状态。我看到这是singleton-scope在 Spring 的配置文件中配置的。我有一种奇怪的感觉,这可能会导致潜在的比赛条件。那是对的吗?

我真的不确定这是否确实如此,但如果它是真的,恕我直言,弄清楚这将是一个噩梦般的情况。我知道这可能不是最好的设计,但我只是想知道当并发线程查询不同的itemTypes. 我正在考虑将范围更改为prototype但不确定在这种情况下是否确实需要。

4

2 回答 2

2

如果多个线程正在调用setItemType(...)然后调用findObj(...)并期望找到具有 iditem-type 的对象,那么是的,你奇怪的感觉是正确的,这是一个潜在的竞争条件,在多线程应用程序中不起作用.

相反,您应该将 传递itemType给您的每个方法:

public boolean findObj(String itemType, int id){...} 
public boolean deleteObj(String itemType, int id){...}
public boolean updateObj(String itemType, Obj obj){...}

如果 itemType 在 Spring 构建 DAO 后仅设置一次,那么这没关系,但应该作为单线程完成的 Spring 配置的一部分来完成。

如果您必须为itemType所有或大多数方法添加参数,那么在我看来您不再应该有一个单例。相反,您应该考虑拥有一个 DAO 工厂或其他东西,并拥有多个 DAO 实例,每个实例都有自己的项目类型。

于 2012-08-22T21:02:57.947 回答
2

如果该setItemType方法用于初始化(例如通过 Spring 配置)并且如果 Spring 强制执行适当的内存屏障以确保该值在使用前在所有线程中可见,那么它可能没问题 - 但有点异味。这是构造函数注入更简洁的地方,因为您可以将其设为final变量,这显然不是什么大问题。

如果在初始化setItemType使用该方法,那么这绝对是一个问题。您要么需要多个实例(例如,每个类需要一个 DAO 引用),要么每个项目类型可能需要一个实例:声明几个单独的 bean,然后为每个需要 DAO 的类提供对“对”一个取决于它需要哪种类型。

于 2012-08-22T21:03:32.637 回答