java Guice:Singleton.class 和 @Singleton 之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14781471/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Guice: differences between Singleton.class and @Singleton
提问by IAmYourFaja
In Guice, what's the difference between:
在 Guice 中,有什么区别:
// Inside your AbstractModule subclass:
@Override
public void configure() {
bind(Service.class).to(ServiceImpl.class).in(Singleton.class);
}
And:
和:
@Override
public void configure() {
bind(Service.class).to(ServiceImpl.class);
}
@Provides @Singleton
public ServiceImpl providesService() {
return new ServiceImpl();
}
Are they both the same? When would you use one versus the other? Thanks in advance.
他们两个一样吗?你什么时候会使用一个和另一个?提前致谢。
回答by Jeff Bowman
They are nearlyidentical. The @Singleton
syntax is useful for annotating @Provides
methods, or annotating the class itself (though I prefer to keep my scoping annotations inside modules).
它们几乎相同。该@Singleton
语法对于注释@Provides
方法或注释类本身很有用(尽管我更喜欢将范围注释保留在模块内)。
The difference lies in which key is marked Singleton, which has less to do with @Singleton
versus Singleton.class
(or Scopes.SINGLETON
, asEagerSingleton
, @Singleton
class annotations, or toInstance
implicit singletons) and more to do with what the default syntax makes easy. For example:
区别在于哪个键被标记为 Singleton,它与@Singleton
vs Singleton.class
(或Scopes.SINGLETON
, asEagerSingleton
,@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(); }
}
Above we've bound interface A
to class AImpl
, and interface B
to class BImpl
, but the behavior is different:
上面我们已经将 interface 绑定A
到 class AImpl
,并将 interface绑定B
到 class BImpl
,但行为是不同的:
- Injecting
A
will retrieve the sameAImpl
instance every time. - Injecting
AImpl
will retrieve a differentAImpl
every time, all of which are different thanA
's instance. - Injecting
B
will retrieve the sameBImpl
instance every time. - Injecting
BImpl
will also retrieve that sameBImpl
instance thatB
injects.
- 每次注入
A
都会检索相同的AImpl
实例。 - Injecting每次
AImpl
都会检索一个不同的AImpl
,所有这些都不同于A
的实例。 - 每次注入
B
都会检索相同的BImpl
实例。 - 注入
BImpl
还将检索注入的相同BImpl
实例B
。
As you can see, each key is different, and Guice will allow multiple implementation instances if only the interface is bound with Singleton. If you only ever inject A
and B
interfaces, the behavior looks identical, but if you inject both interfaces and implementations from the same Injector, you may see differing behavior.
可以看到,每个key都不一样,只要接口绑定Singleton,Guice就会允许多个实现实例。如果你只注入A
和B
接口,行为看起来是一样的,但如果你从同一个注入器注入接口和实现,你可能会看到不同的行为。
Similar logic goes for @Provides
methods:
类似的逻辑适用于@Provides
方法:
- Injecting
C
will always return the sameCImpl
instance. - Injecting
CImpl
will create a newCImpl
every time, unlessCImpl
has no injectable public zero-arg constructor—then the injection will fail. - Injecting
D
will always return the sameDImpl
instance. - Injecting
DImpl
will return a new instance every time, and each will be different than the one returned byD
. - Injecting
E
will return the sameEImpl
instance every time. - Injecting
EImpl
will also retrieve that same instanceE
injects.
- 注入
C
将始终返回相同的CImpl
实例。 - 每次注入
CImpl
都会创建一个新的CImpl
,除非CImpl
没有可注入的公共零参数构造函数——否则注入将失败。 - 注入
D
将始终返回相同的DImpl
实例。 - Injecting
DImpl
每次都会返回一个新的实例,并且每次都会与D
. - 每次注入
E
都会返回相同的EImpl
实例。 - 注入
EImpl
还将检索相同的实例E
注入。
This provides some flexibility. Imagine a hypothetical Cache
that keeps a certain number of most-recently-retrieved objects, where you want to have @User Cache
and @Product Cache
both injectable. If you bind(Cache.class).in(Singleton.class)
, you will have one Cache shared between the objects (and any bare Cache
injections), whereas if you bind(Cache.class).annotatedWith(User.class).to(Cache.class).in(Singleton.class)
then the annotated key is kept in singleton scope and each object type will have its own cache.
这提供了一些灵活性。想象一个假设Cache
,其中保留了一定数量的最近检索到的对象,您希望在其中拥有@User Cache
并且@Product Cache
都可以注入。如果你bind(Cache.class).in(Singleton.class)
,你将在对象(和任何裸Cache
注入)之间共享一个缓存,而如果你bind(Cache.class).annotatedWith(User.class).to(Cache.class).in(Singleton.class)
然后注释键保持在单例范围内,并且每个对象类型都将有自己的缓存。