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

Java Guice:Singleton.class和@Singleton之间的区别,java,dependency-injection,singleton,guice,Java,Dependency Injection,Singleton,Guice,在Guice中,以下两者之间的区别是什么: // Inside your AbstractModule subclass: @Override public void configure() { bind(Service.class).to(ServiceImpl.class).in(Singleton.class); } 以及: 他们都一样吗?你什么时候会用一个来对比另一个?提前谢谢。它们几乎一模一样。@Singleton语法对于注释@提供的方法或注释类本身非常有用(尽管我更喜欢将作

在Guice中,以下两者之间的区别是什么:

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


他们都一样吗?你什么时候会用一个来对比另一个?提前谢谢。

它们几乎一模一样。
@Singleton
语法对于注释
@提供的
方法或注释类本身非常有用(尽管我更喜欢将作用域注释保留在模块中)

区别在于哪个键被标记为Singleton,这与
@Singleton
Singleton.class
相比关系不大(或者
作用域.Singleton
asagersingleton
@Singleton
类注释,或者
到instance
隐式Singleton)还有更多的工作要做,默认语法使之变得简单。例如:

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将允许多个实现实例。如果只注入
A
B
接口,行为看起来是相同的,但是如果从同一个注入器注入两个接口和实现,则可能会看到不同的行为

类似的逻辑适用于
@提供了
方法:

  • 注入
    C
    将始终返回相同的
    CImpl
    实例
  • 每次注入
    CImpl
    都将创建一个新的
    CImpl
    ,除非
    CImpl
    没有可注入的公共零参数构造函数,否则注入将失败
  • 注入
    D
    将始终返回相同的
    DImpl
    实例
  • 注入
    DImpl
    将每次返回一个新实例,并且每个实例都不同于
    D
    返回的实例
  • 注入
    E
    将每次返回相同的
    EImpl
    实例
  • 注入
    EImpl
    也将检索相同的实例
    E
    injects

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

我遇到过这样的情况,它们的行为似乎有所不同。使用bind语句并没有限制为仅使用1个实例。不过,使用@Singleton它还是有效的。@EFreak:更新了答案。这并不完全是语法上的差异,但从新的角度来看这个问题,这里有一些微妙之处。非常感谢!这正是我昨天面临的问题。不过,我有一个编辑建议。将更新答案。
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(); }
}