我正在使用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。但事实并非如此。
我做错了什么?
答案 0 :(得分:1)
您可能已经检查了这一点 - 您已经列出了“您使用的那种”的绑定 - 但值得仔细检查,在您的非编辑代码中,所有涉及的类都不会被{{1}谨慎注释}或绑定到@Singleton
范围。此外,确保没有任何绑定使用Singleton.class
,这当然总是在所有情况下返回预先构造的实例,并且实际上是单例绑定。
我们有一个案例,我们重构了toInstance()
方法并最终忘记我们将其设置为始终将其参数绑定为单例(这样视图的父容器和视图的控制器可以注入相同的观点)。
除非Danyel提到,否则circular dependency detection会被编入Guice,并且由于您在bindView
注释方法中调用了provider.get()
,因此您可能正在调用它。
答案 1 :(得分:0)
如果您查看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
变量中。现在,根据此代码片段,它会在注入时立即释放。所以,可能在你的“范围”中它可能在其他地方初始化,可能在注射开始时 - 并且在注射结束时,它被释放。