繁体   English   中英

guice-提供者总是返回相同的实例

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM