最近我们的系统一直在经历各种与 Spring 相关的“巫毒”。它通常是这样的:
各种单例 bean 具有(ctor)自动装配属性,它们基于这些属性实例化一些内部数据结构。在某些时候,我们开始看到内部状态未初始化的现象,尽管事实上构建了 bean 并将其分发给应用程序。它当然是以非确定性的方式发生的。
一个典型的 bean 看起来像这样:
class MyBean{
Map<String, Objecet> state;
@Autowired
public MyBean(List<Stuff> stuff){
state = new HashMap<>();
pupolateStateBasedOnStuff();
}
getSomeState(String key){
// I would get an NPE (state = null) or an instantiated
// state that is seemingly empty!
state.get(key);
}
}
在某些时候,我偶然发现了这篇文章和这个 SO 答案以及Brian Goetz 的这篇文章。我正遭受这个问题的困扰。阅读完这些后,我有两个后续问题:
山羊写道:
因此,您可以拥有一个指向数组的最终指针,而不必担心其他线程会看到数组引用的正确值,但数组内容的值不正确
问题 1
这个陈述是及物的吗?这意味着这不仅适用于最终变量引用的对象,还适用于它们引用的对象等(覆盖整个“可达”对象树)?
另外,如果我有以下情况怎么办:
class Bar{
volatile Foo foo;
public Bar() { }
// Bar is actually initialized outside of its ctor.
public init(Object state) {
foo = new Foo(state);
}
getSomeStuff(){
// will 'stuff' be fully visible because it
// was created by assignment to a final variable?
return foo.stuff;
}
}
Foo 看起来像这样:
class Foo{
final Object stuff ;
Foo(Object state){
this.stuff = computeStuff(state);
}
}
问题2
这个“技巧”是否确保了“东西”的可见性?
换句话说 - 我有一个在其 ctor 之外初始化的类(不能有最终成员)。但我仍然想确保能见度。因此,我将状态包装在一个对象中,该对象将其分配给其 ctor 内的最终变量。