guice - Provider总是返回相同的实例

时间:2013-02-07 10:09:23

标签: java dependency-injection guice guice-servlet

我正在使用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。但事实并非如此。

我做错了什么?

2 个答案:

答案 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变量中。现在,根据此代码片段,它会在注入时立即释放。所以,可能在你的“范围”中它可能在其他地方初始化,可能在注射开始时 - 并且在注射结束时,它被释放。