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

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


答案 1

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

区别在于哪个键被标记为单例,这与与(或,,类注释或隐式单例)的关系较小,而与默认语法变得容易有关。例如:@SingletonSingleton.classScopes.SINGLETONasEagerSingleton@SingletontoInstance

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

上面我们已经将接口绑定到类,并将接口绑定到类,但行为是不同的:AAImplBBImpl

  • 注入每次都会检索相同的实例。AAImpl
  • 注入每次都会检索不同的实例,所有这些实例都与 的实例不同。AImplAImplA
  • 注入每次都会检索相同的实例。BBImpl
  • 注入还将检索注入的同一实例。BImplBImplB

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

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

  • 注入将始终返回相同的实例。CCImpl
  • 注入每次都会创建一个新的,除非没有可注入的公共零参数构造函数,否则注入将失败。CImplCImplCImpl
  • 注入将始终返回相同的实例。DDImpl
  • 注入每次都会返回一个新实例,每个实例都与 返回的实例不同。DImplD
  • 注入每次都会返回相同的实例。EEImpl
  • 注入还将检索相同的实例注入。EImplE

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


答案 2

推荐