假设以下类是单身
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提供了一些状态。我在Spring的配置文件中看到它被配置为singleton-scope
。我有一种奇怪的感觉,这可能导致潜在的竞争条件。这是对的吗?
我真的不确定这是否确实如此,但如果确实如此,恕我直言就是噩梦般的情况。我知道这可能不是最好的设计,但我只是想知道当并发线程查询不同的itemTypes
时是否会导致竞争条件。我在考虑将范围更改为prototype
,但我不确定在这种情况下是否确实需要。
答案 0 :(得分:2)
如果多个线程正在调用setItemType(...)
然后调用findObj(...)
并且期望找到具有id 和的项目类型的对象然后是,那么你的奇怪感觉这是正确的,这是一种潜在的竞争条件,不适用于多线程应用程序。
您应该将itemType
传递给您的每个方法:
public boolean findObj(String itemType, int id){...}
public boolean deleteObj(String itemType, int id){...}
public boolean updateObj(String itemType, Obj obj){...}
如果在Spring构造DAO之后只设置了一次itemType,那么这是可以的,但应该作为Spring配置的一部分完成,这是单线程完成的。
如果你必须为所有或大多数方法添加一个itemType
参数,那么在我看来你不再需要一个单例。相反,您应该考虑拥有DAO工厂或其他东西,并拥有多个DAO实例,每个实例都有自己的项类型。
答案 1 :(得分:2)
如果setItemType
方法仅在初始化时使用(例如通过Spring配置),并且如果Spring强制执行适当的内存屏障以确保在使用前所有线程中都显示该值,那么它可能还可以 - 但有点气味。这是构造函数注入更整洁的地方,因为你可以将它变成final
变量,这显然不是一个问题。
如果使用setItemType
方法 post 初始化,那肯定是肯定一个问题。您将需要遍布整个地方的多个实例(例如,每个类需要一个DAO引用一个)或每个项类型可能有一个实例:声明几个单独的bean,然后为每个需要DAO的类提供对“对“一个取决于它需要哪种类型。