当我们想要有条件地初始化一些 bean 的字段时使用后构造方法,我们是否需要关心字段的波动性,因为它是一个多线程环境?
比如说,我们有这样的东西:
@ApplicationScoped
public class FooService {
private final ConfigurationService configurationService;
private FooBean fooBean;
@Inject
FooService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
void init(@Observes @Initialized(ApplicationScoped.class) Object ignored) {
if (configurationService.isFooBeanInitialisationEnabled()) {
fooBean = initialiseFooBean(configurationService); // some initialisation
}
}
void cleanup(@Observes @Destroyed(ApplicationScoped.class) Object ignored) {
if (fooBean != null) {
fooBean.cleanup();
}
}
}
那么 fooBean
应该被包装到比方说 AtomicReference
中还是 volatile
或者它会是一个多余的额外保护?
P.S. 在这种特殊情况下,它可以重新表述为:post construct 和 post destroy 事件是否由同一线程执行?但是,我想对更一般的情况有一个答案。
最佳答案
我会说这取决于哪个线程实际启动和销毁上下文。
如果您使用常规事件,它们是同步的(异步事件已添加到 CDI 2.0 中,带有 ObservesAsync
,请参阅
Java EE 8: Sending asynchronous CDI 2.0 events with ManagedExecutorService ) 因此它们在与调用者相同的线程中被调用。
一般来说,我不认为使用相同的线程(在应用程序服务器或独立应用程序中)所以我建议使用 volatile
来确保看到正确的值(基本上是看到构造的值在销毁线程)。但是,以并发方式启动和销毁您的应用程序并不是经常发生的用例...
关于java - CDI PostConstruct 和可变字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53227585/