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

时间:2013-02-08 21:14:16

标签: java dependency-injection singleton guice

在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();
}

他们俩都一样吗?你什么时候使用一个?提前谢谢。

1 个答案:

答案 0 :(得分:18)

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

不同之处在于哪个键标记为Singleton ,与@SingletonSingleton.class(或Scopes.SINGLETONasEagerSingleton相关性较小,@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(); }
}

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

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

正如您所看到的,每个键都是不同的,如果只有接口与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次注入),而如果您bind(Cache.class).annotatedWith(User.class).to(Cache.class).in(Singleton.class)则注释的密钥将保留在单一范围内,并且每个对象类型将拥有自己的缓存。