【问题标题】:How to use guice injection for an existing singleton class?如何为现有的单例类使用 guice 注入?
【发布时间】:2017-04-14 00:02:52
【问题描述】:

我有一个名为 Legacy 的现有类,它主要是用老式单例模式编写的。现在我想为它引入一个新领域,我想使用 Guice。 Legacy 本身不受 Guice 控制,它被另一个 Service 类使用(在 Service 类内部,它现在调用 Legacy 类的 getInstance() 来检索 Legacy 对象),并且该 Service 类是使用 Guice 注入器创建的。

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 放入 Legacy 类

@Inject
public void setNewField(NewField newObj) {
  this.newObj = newObj;
}

并且在Service的模块文件中,我绑定了NewField对象,但是当我运行程序时,它抛出了一个NullPointer异常。所以注入不起作用。知道如何将 NewField 注入到我的程序中,同时保持当前的老式单例范式,并且不对其他所有内容进行太多更改吗?

编辑 下面至少有三个解决方案,我不太清楚哪个是最好的或者它们是否等效。

【问题讨论】:

  • 这 3 种解决方案或多或少是等效的。他们都在你的单身人士身上(直接或间接)打电话给injectMembers

标签: java dependency-injection guice


【解决方案1】:

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

// put in the module
bind(Legacy.class).toInstance(Legacy.getInstance());

在此示例中,您的模块本身而不是 Guice 负责获取 Legacy 实例,然后要求 Guice 始终使用此单个实例来满足所有 Legacy 注入请求。 但根据javadoc 创建 Injector 时,它会自动为该实例执行字段和方法注入,但 Legacy 上的任何可注入构造函数都将被忽略。请注意,使用这种方法会导致您无法控制的“急切加载”行为。

【讨论】:

  • 这个解决方案还有一个额外的好处,你甚至可以使用@Inject Legay legacy; 将你的单例注入到其他类中。
【解决方案2】:

虽然只比 Thomas 的回答稍微干净一些,但您可以使用 requestInjectionrequestStaticInjection 从模块中配置单例注入。

// In your Module:
requestInjection(Legacy.getInstance());  // for an instance field, or
requestStaticInjection(Legacy.class);    // for a static field.

docs on the wiki 警告其缺点:

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

【讨论】:

    【解决方案3】:

    这是一个有点老套的解决方案。

    在您的应用程序的引导过程中, 可能在方法public static void main(String[] args)中, 你应该已经有类似这样的代码:

    Injector injector = Guice.createInjector(yourModule);
    

    在此处添加以下行:

    injector.injectMembers(Legacy.getInstance());
    

    通过这样做,您的 Legacy 单例中的所有 @Injects 应该解决。
    另请参阅Injector.injectMembers 的 javadoc。

    【讨论】:

      猜你喜欢
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多