我正在使用guice 3和guice-servlet 3。在模块中,我定义了这样的绑定:
[...]
bind(View.class).annotatedWith(Names.named("view1")).to(View1Impl.class);
bind(View.class).annotatedWith(Names.named("view2")).to(View2Impl.class);
[...]在注入类View1Impl中,我定义了以下内容:
public class View1Impl {
@Inject @Named("view1") Provider<View> viewProvider;
@Inject
void init() {
View viewA = viewProvider.get();
View viewB = viewProvider.get();
log.debug(viewA == viewB);
log.debug(viewA == this);
}
}这两个语句都返回true。但事实并非如此。
我做错了什么?
发布于 2013-02-08 01:34:02
如果你看一下Guice的源代码,就会很清楚实际做了什么:
final ThreadLocal<Object[]> localContext;
/** Looks up thread local context. Creates (and removes) a new context if necessary. */
<T> T callInContext(ContextualCallable<T> callable) throws ErrorsException {
Object[] reference = localContext.get();
if (reference[0] == null) {
reference[0] = new InternalContext();
try {
return callable.call((InternalContext)reference[0]);
} finally {
// Only clear the context if this call created it.
reference[0] = null;
}
} else {
// Someone else will clean up this context.
return callable.call((InternalContext)reference[0]);
}
}显然,当您的对象被注入时,Guice将其存储在ThreadLocal变量中。现在,根据这个代码片段,它将在注入时立即释放。
发布于 2013-02-08 01:04:21
您可能已经检查过这一点--列出了“所使用的类型”的绑定--但值得仔细检查的是,在未编辑的代码中,涉及的任何类都没有谨慎地用@Singleton注释或绑定到Singleton.class作用域。此外,确保您的任何绑定都不使用toInstance(),它当然在所有情况下都将始终返回预先构造的实例,并且是有效的单例绑定。
我们有一个案例,我们重构了一个bindView方法,但最终忘记了我们将它设置为总是将其参数绑定为单例(这样视图的父容器和视图的控制器可以注入相同的视图)。
除非,正如Danyel提到的那样,有circular dependency detection编码到Guice中,而且由于您是在@Inject-annotated方法中调用provider.get(),所以您可能会调用它。
https://stackoverflow.com/questions/14748442
复制相似问题