我有类“RequestContext
”,它的范围是request
。此类具有属性 listOfItem
。
现在我有类 MyMapper
,我需要在其中使用此列表。现在,当我想要 listOfItems
时,我总是调用 context.getListOfItem()
但问题是我有很多私有(private)方法,我需要在其中重复很多次。当我在构造函数中定义这个属性时可以吗?它是线程安全的吗?:
public abstract class MyMapper{
@Autowired
protected RequestContext context;
private final List<String> listOfItem;
public MyMapper() {
this.listOfItem = context.getListOfItem(); // is this thread safe and ok ?
}
public Object map(Object entity){
}
}
最佳答案
是的,那是线程安全的只要声明为原型(prototype)范围bean,并且您需要创建一个由Spring 调用的init()
方法:
@PostConstruct
public void init() {
listOfItem = context.getListOfItem();
}
RequestContext 只能从单线程(分配用于处理请求的线程)访问,构造函数在调用之前创建对象的本质是不可重入的。
注意不要将它与 listOfItem
混淆,尽管它以某种方式避免重入问题,只是因为它被锁定在 MyMapper
对象中并不能阻止它被由 setter/getter 共享,如果有的话(在你的情况下没有)。我还看到它是一个抽象类,但是因为 listOfItem
是私有(private)的,子类将无法访问它。如果存在引用的任何副本(因为 List
在 Java 中是可变的),则该 List 的任何泄漏引用都可以由并发线程操作。
由于这种安全性是您的意图,因此创建一个单元测试来检查该字段的可见性,如果通过反射访问该字段没有抛出适当的异常,则测试失败。您可能还想用您自己的内部标记注释来注释该字段,以指示该字段是线程安全的。这有助于记录,并作为注释,潜在的 future 自动化(例如可以查找所有此类注释并自动运行反射测试的测试库)。
看起来很干净!继续努力。
关于java - 使用请求范围时的线程安全代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29896940/