java使用“setter”/实例变量会导致单例DAO的竞争条件吗?
假设下面的类是单例
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
,但不确定在这种情况下是否确实需要它
# 1 楼答案
如果多个线程正在调用
setItemType(...)
,然后调用findObj(...)
,并且希望找到id为且项目类型为的对象,那么是的,您的奇怪感觉是正确的,这是一种潜在的竞争条件,在多线程应用程序中不起作用您应该将
itemType
传递给每个方法:如果在Spring构建DAO之后只设置一次itemType,那么这是可以的,但是应该作为Spring配置的一部分来完成,Spring配置是单线程完成的
如果您必须向所有或大多数方法添加
itemType
参数,那么在我看来,您不应该再使用单例。相反,你应该考虑有一个刀工厂或一些东西,并且有多个DAO实例,每个都有自己的项目类型。# 2 楼答案
如果
setItemType
方法只在初始化时使用,(例如,通过Spring配置),并且如果Spring强制执行适当的内存屏障,以确保在使用前所有线程中都可以看到该值,那么它可能没问题,但有点异味。这就是构造器注入更简洁的地方,因为您可以将其设置为final
变量,这显然不是什么大问题如果在初始化之后使用
setItemType
方法,那么这肯定是一个问题。您可能需要到处都有多个实例(例如,每个类需要一个DAO引用),或者每个项类型可能需要一个实例:声明几个单独的bean,然后根据需要的类型为每个需要DAO的类提供一个“正确”实例的引用