Guice:在这种情况下,如何配置模块中的@Provides和@Singleton?

28

我有一个模块中带有@Provides注解的提供者方法:

@Provides
public ChatServicePerformanceMonitor getChatServicePerfMon() {
  ...
}

我已经用@Singleton给我的ChatServicePerformanceMonitor添加了注释。在我的代码中,当我使用这个实例时,由于我使用的框架正在构造封闭类(它不使用Guice,所以这是我知道的唯一方法来获取引用),我无法让guice “被动”注入它:

chatServicePerfMon = injector.getInstance(ChatServicePerformanceMonitor.class);
似乎Guice没有尊重我的ChatServicePerformanceMonitor类上的@Singleton注释。每次调用injector.getInstance(ChatServicePerformanceMonitor.class)都会获得一个实例。
将@Singleton添加到提供程序方法似乎可以解决这个问题:
@Provides @Singleton
public ChatServicePerformanceMonitor getChatServicePerfMon() {
  ...
}

这是期望的行为吗?似乎只需要在实例上使用 @Singleton 就足够了。


2
你是如何在第一段代码片段中创建 ChatServicePerformanceMonitor 的?如果 Guice 没有在你的 getChatServicePerfMon 方法中创建它,那么 @Singleton 将会被忽略。 - condit
1
是的,它是在@Provider方法内部构建的,几乎与此处中的provideTransactionLog方法描述的完全相同。看起来这一定是我在做什么事情,因为其他人一定也遇到了这个问题。但是除了我直接从注入器获取实例之外,我没有看到任何与他们的示例不同的地方。 - Alper Akture
3个回答

31

23

如果你是这样创建ChatServicePerformanceMonitor的:

@Provides
public ChatServicePerformanceMonitor getChatServicePerfMon() {
  return new ChatServicePerformanceMonitor();
}

如果您的类级别有@Singleton注释,因为Guice不创建对象而是您创建,所以该注释将没有任何效果。Guice只能强制执行其创建的对象的范围。将@Singleton添加到getChatServicePerfMon()方法中没有任何问题。

如果在ChatServicePerformanceMonitor类上有一个无参构造函数(或@Inject构造函数),并且您删除了@Provides方法,则对注入器的连续调用将返回相同的单例对象。


2
好的,谢谢。我正在那里尝试新的东西。我猜想既然Guice调用了我的提供者方法,我认为它仍然会强制执行Singleton行为(因为我不调用提供者方法,他们调用),并且可以管理它。看来我错了! - Alper Akture
我不知道你在使用哪个框架,但你也可以使用Guice来创建封闭实例(即使你不能注入它),通过Provider(或@Provides)。这样该对象就可以与其他Guice依赖项协作。 - condit
谢谢,是的,我已经找了一段时间的方法来做到这一点,但这个框架的“工作方式”是我扩展他们的一个类。当他们启动时(它是一个名为SmartFox的游戏服务器),他们会引导所有东西,并进行扩展类实例化。我不认为有办法让Guice拦截它,对吗? - Alper Akture
6
通常而言,使用DI/Guice时,永远不要使用“new”这个词。 - Jan Galinski
Guice只能在它创建的对象上强制执行作用域。Guice正在创建该对象。它只是调用我们的“Provides”方法,而不是调用类构造函数。我看不出为什么它不能在这种情况下遵守“@Singleton”类注释。 - Eric

-6

你总是可以采用最简单的方法:

private ChatServicePerformanceMonitor perfMon = null;

@Provides
public ChatServicePerformanceMonitor getChatServicePerfMon() {
  if (perfMon == null) {
    perfMon = new ChatServicePerformanceMonitor();
  }

  return perfMon;
}

5
这段话的意思是“这似乎不是线程安全的,应该在方法上加入synchronized关键字。” - kcraigie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接