java Guice:Singleton.class 和 @Singleton 之间的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14781471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 17:22:20  来源:igfitidea点击:

Guice: differences between Singleton.class and @Singleton

javadependency-injectionsingletonguice

提问by IAmYourFaja

In Guice, what's the difference between:

在 Guice 中,有什么区别:

// Inside your AbstractModule subclass:
@Override
public void configure() {
    bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
}

And:

和:

@Override
public void configure() {
    bind(Service.class).to(ServiceImpl.class);
}

@Provides @Singleton
public ServiceImpl providesService() {
    return new ServiceImpl();
}

Are they both the same? When would you use one versus the other? Thanks in advance.

他们两个一样吗?你什么时候会使用一个和另一个?提前致谢。

回答by Jeff Bowman

They are nearlyidentical. The @Singletonsyntax is useful for annotating @Providesmethods, or annotating the class itself (though I prefer to keep my scoping annotations inside modules).

它们几乎相同。该@Singleton语法对于注释@Provides方法或注释类本身很有用(尽管我更喜欢将范围注释保留在模块内)。

The difference lies in which key is marked Singleton, which has less to do with @Singletonversus Singleton.class(or Scopes.SINGLETON, asEagerSingleton, @Singletonclass annotations, or toInstanceimplicit singletons) and more to do with what the default syntax makes easy. For example:

区别在于哪个键被标记为 Singleton,它与@Singletonvs Singleton.class(或Scopes.SINGLETON, asEagerSingleton@Singleton类注释,或toInstance隐式单例)的关系不大,而更多地与默认语法的简单性有关。例如:

public class MyModule extends AbstractModule {
  @Override public void configure() {
    bind(A.class).to(AImpl.class).in(Singleton.class);

    bind(B.class).to(BImpl.class);
    bind(BImpl.class).in(Singleton.class);
  }

  @Provides @Singleton C provideC() { return new CImpl(); }

  @Provides @Singleton D provideD(DImpl dImpl) { return dImpl; }

  @Provides E provideE(EImpl eImpl) { return eImpl; }
  @Provides @Singleton EImpl provideEImpl() { return new EImpl(); }
}

Above we've bound interface Ato class AImpl, and interface Bto class BImpl, but the behavior is different:

上面我们已经将 interface 绑定A到 class AImpl,并将 interface绑定B到 class BImpl,但行为是不同的:

  • Injecting Awill retrieve the same AImplinstance every time.
  • Injecting AImplwill retrieve a different AImplevery time, all of which are different than A's instance.
  • Injecting Bwill retrieve the same BImplinstance every time.
  • Injecting BImplwill also retrieve that same BImplinstance that Binjects.
  • 每次注入A都会检索相同的AImpl实例。
  • Injecting每次AImpl都会检索一个不同的AImpl,所有这些都不同于A的实例。
  • 每次注入B都会检索相同的BImpl实例。
  • 注入BImpl还将检索注入的相同BImpl实例B

As you can see, each key is different, and Guice will allow multiple implementation instances if only the interface is bound with Singleton. If you only ever inject Aand Binterfaces, the behavior looks identical, but if you inject both interfaces and implementations from the same Injector, you may see differing behavior.

可以看到,每个key都不一样,只要接口绑定Singleton,Guice就会允许多个实现实例。如果你只注入AB接口,行为看起来是一样的,但如果你从同一个注入器注入接口和实现,你可能会看到不同的行为。

Similar logic goes for @Providesmethods:

类似的逻辑适用于@Provides方法:

  • Injecting Cwill always return the same CImplinstance.
  • Injecting CImplwill create a new CImplevery time, unless CImplhas no injectable public zero-arg constructor—then the injection will fail.
  • Injecting Dwill always return the same DImplinstance.
  • Injecting DImplwill return a new instance every time, and each will be different than the one returned by D.
  • Injecting Ewill return the same EImplinstance every time.
  • Injecting EImplwill also retrieve that same instance Einjects.
  • 注入C将始终返回相同的CImpl实例。
  • 每次注入CImpl都会创建一个新的CImpl,除非CImpl没有可注入的公共零参数构造函数——否则注入将失败。
  • 注入D将始终返回相同的DImpl实例。
  • InjectingDImpl每次都会返回一个新的实例,并且每次都会与D.
  • 每次注入E都会返回相同的EImpl实例。
  • 注入EImpl还将检索相同的实例E注入。

This provides some flexibility. Imagine a hypothetical Cachethat keeps a certain number of most-recently-retrieved objects, where you want to have @User Cacheand @Product Cacheboth injectable. If you bind(Cache.class).in(Singleton.class), you will have one Cache shared between the objects (and any bare Cacheinjections), whereas if you bind(Cache.class).annotatedWith(User.class).to(Cache.class).in(Singleton.class)then the annotated key is kept in singleton scope and each object type will have its own cache.

这提供了一些灵活性。想象一个假设Cache,其中保留了一定数量的最近检索到的对象,您希望在其中拥有@User Cache并且@Product Cache都可以注入。如果你bind(Cache.class).in(Singleton.class),你将在对象(和任何裸Cache注入)之间共享一个缓存,而如果你bind(Cache.class).annotatedWith(User.class).to(Cache.class).in(Singleton.class)然后注释键保持在单例范围内,并且每个对象类型都将有自己的缓存。