Java 如何对现有的单例类使用guice注入?

Java 如何对现有的单例类使用guice注入?,java,dependency-injection,guice,Java,Dependency Injection,Guice,我有一个名为Legacy的现有类,它大部分是用旧式的单例模式编写的。现在我想为它引入一个新的字段,我想使用Guice。Legacy本身不是Guice控制的,它由另一个服务类使用(在服务类内部,它现在调用Legacy类的getInstance()来检索Legacy对象),并且该服务类是使用Guice injector创建的 public class Legacy { public synchronized static Legacy getInstance() { if(sI

我有一个名为Legacy的现有类,它大部分是用旧式的单例模式编写的。现在我想为它引入一个新的字段,我想使用Guice。Legacy本身不是Guice控制的,它由另一个服务类使用(在服务类内部,它现在调用Legacy类的getInstance()来检索Legacy对象),并且该服务类是使用Guice injector创建的

public class Legacy {

   public synchronized static Legacy getInstance() {
       if(sInstance == null) {
           sInstance = new Legacy();
       }
       return sInstance;
   }

   private Legacy() {
       legacyObj = LegacyField.getInstance(); // get a singleton
   }

   private static Legacy sInstance;

   private LegacyField legacyObj;

   private NewField newObj; // this is the new dependency I would like to add using Guice
}
我尝试的是将方法注入到遗留类中

@Inject
public void setNewField(NewField newObj) {
  this.newObj = newObj;
}
在服务的模块文件中,我绑定了NewField对象,但是当我运行程序时,它抛出了一个NullPointer异常。所以注射不起作用。有没有想过如何让NewField注入到我的程序中,但保持当前的旧式单身模式,而不改变太多其他方面的内容

编辑
下面至少有三个解决方案,我不知道哪一个是最好的,或者它们是等效的

这里有一个有点粗俗的解决方案

在应用程序的引导过程中, 可能在方法
公共静态void main(字符串[]args)
中, 您应该已经有类似于以下内容的代码:

Injector injector = Guice.createInjector(yourModule);
在此处添加以下行:

injector.injectMembers(Legacy.getInstance());
这样,所有的
@注入
到您的
遗留
单例中 应该解决。

另请参阅的javadoc。

尽管只比Thomas的答案稍微简洁,但您可以使用或在模块内配置单例注入

不过,政府警告说,这会带来负面影响:

不建议将此API用于一般用途,因为它遇到许多与静态工厂相同的问题:测试起来很笨拙,使依赖项不透明,并且依赖于全局状态


我刚刚找到了另一个解决方案:

// put in the module
bind(Legacy.class).toInstance(Legacy.getInstance());
在本例中,您的模块本身(而不是Guice)负责获取遗留实例,然后要求Guice始终使用此单个实例来完成所有遗留注入请求。 但是根据
创建注入器时,它将自动为此实例执行字段和方法注入,但只会忽略遗留上的任何可注入构造函数。请注意,使用此方法会导致无法控制的“急切加载”行为。

此解决方案还有一个额外的好处,您甚至可以使用
@injectlegay Legay将你的单例注入到其他类中。这3种解决方案或多或少是等效的。他们都(直接或间接地)调用你的单身汉的
injectMembers
// put in the module
bind(Legacy.class).toInstance(Legacy.getInstance());