Guice:Singleton.class和@Singleton之间的差异

在Guice,有什么区别:

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

和:

 @Override public void configure() { bind(Service.class).to(ServiceImpl.class); } @Provides @Singleton public ServiceImpl providesService() { return new ServiceImpl(); } 

它们都是一样的吗? 你什么时候使用一个? 提前致谢。

它们几乎相同。 @Provides语法对于注释@Provides方法或注释类本身很有用(尽管我更喜欢在模块中保留我的作用域注释)。

不同之处在于哪个键标记为Singleton ,它与Scopes.SINGLETONSingleton.class (或Scopes.SINGLETONasEagerSingletonScopes.SINGLETON Singleton.class类注释或toInstance隐式单例)关系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(); } } 

上面我们将接口A绑定到类AImpl ,将接口B绑定到类BImpl ,但行为不同:

  • 注入A将每次检索相同的AImpl实例。
  • 注入AImpl将每次检索不同的AImpl ,所有这些都与A的实例不同。
  • 注入B将每次检索相同的BImpl实例。
  • 注入BImpl还将检索B注入的相同BImpl实例。

如您所见,每个键都是不同的,如果只有接口与Singleton绑定,Guice将允许多个实现实例。 如果您只注入AB接口,则行为看起来相同,但如果您从同一个Injector注入接口和实现,则可能会看到不同的行为。

@Provides方法也有类似的逻辑:

  • 注入C将始终返回相同的CImpl实例。
  • 注入CImpl都会创建一个新的CImpl ,除非CImpl没有可注入的公共零参数构造函数 – 然后注入将失败。
  • 注入D将始终返回相同的DImpl实例。
  • 注入DImpl将每次返回一个新实例,每个实例将与D返回的实例不同。
  • 注入E将每次返回相同的EImpl实例。
  • 注入EImpl也将检索相同的实例E注入。

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