[英]guice - Provider returns always same instance
我正在使用guice 3和guice-servlet3。在模块中,我定义了这种绑定:
[...]
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。 但是事实并非如此。
我究竟做错了什么?
您可能已经检查了这一点-列出了您使用的“那种”绑定-但是值得仔细检查一下,在未编辑的代码中,所有涉及的类都不会用@Singleton
谨慎地注释或绑定到Singleton.class
范围。 此外,请确保没有任何绑定使用toInstance()
,它当然总是在所有情况下都返回该预先构造的实例,并且实际上是单例绑定。
我们遇到了一个案例,我们重构了bindView
方法,最终忘记了将其设置为始终将其参数绑定为单例(这样,视图的父容器和视图的控制器可以注入同一视图)。
除非Danyel暗示过,否则Guice中编码了循环依赖项检测 ,并且由于您正在@Inject
注释方法中调用provider.get()
,因此您可能正在调用它。
如果您查看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
变量中。 现在,根据此代码片段,它将在注入时立即释放。 因此,可能在您的“作用域”中将其初始化为其他位置,可能是在注入开始时-在注入结束时被释放了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.