谷歌guice是否通过setter为注射可变依赖提供安全的出版物保证?

时间:2015-03-11 08:44:23

标签: java dependency-injection guice

有时由于几个原因,我需要通过setter而不是构造函数来使用注入。所以在这些情况下,我不能将字段标记为final,因为字段值需要在构造后更改。如JMM中所述,如果字段不是final,那么另一个线程可以看到该字段没有完全初始化的值。 guice有没有解决这个问题的方法?

换句话说,guice是否提供保证, A 的方法 foo 总是会看到安全的已发布的实例?

public class A {

     // there is no problem with safe publication due to dataSource is final
     private final DataSource dataSource;

     // potential problem with safe publication due to something is not final
     private SomeMutableClass something;

     @Inject
     public A(DataSource dataSource) {
          dataSource = dataSource;
     } 

     @Inject
     public void setSomething(SomeMutableClass something) {
         this.something = something;
     }

     public void foo() {
         // does another thread can observe incompletly initialized value of something? 
         something.doSomething();
     }

}

1 个答案:

答案 0 :(得分:2)

如果我正确理解了这个问题,那就是你在线程1上获得A的实例,并在线程2上调用a.foo()的情况。在这种情况下,Guice等同于手动编写

Thread 1                     Thread 2
-------------------------------------
A a = new A(dataSource);    | // Thread 2 could observe a.something == null
a.setSomething(something);  | a.foo();

但是,只有在没有任何形式的同步的情况下将a从线程1传递到线程2时,才会发生这种情况。 synchronized块,线程安全的数据结构等具有内存排序保证。