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.SINGLETON
与Singleton.class
(或Scopes.SINGLETON
, asEagerSingleton
, Scopes.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将允许多个实现实例。 如果您只注入A
和B
接口,则行为看起来相同,但如果您从同一个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)
然后带注释的键保存在单例范围内,每个对象类型都有自己的缓存。