简体   繁体   English

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

[英]guice - Provider returns always same instance

I am working with guice 3 and guice-servlet 3. In the module I defined bindings of this sort: 我正在使用guice 3和guice-servlet3。在模块中,我定义了这种绑定:

[...]
bind(View.class).annotatedWith(Names.named("view1")).to(View1Impl.class);
bind(View.class).annotatedWith(Names.named("view2")).to(View2Impl.class);
[...]

In the injected class View1Impl I defined following: 在注入的类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);
    }

}

Both statements return true. 两条语句均返回true。 But that should not be the case. 但是事实并非如此。

What am I doing wrong? 我究竟做错了什么?

You might have already checked this--you've listed bindings "of the sort" you use--but it's worth double-checking that in your non-redacted code none of the classes involved are discreetly annotated with @Singleton or bound to the Singleton.class scope. 您可能已经检查了这一点-列出了您使用的“那种”绑定-但是值得仔细检查一下,在未编辑的代码中,所有涉及的类都不会用@Singleton谨慎地注释或绑定到Singleton.class范围。 Furthermore, ensure that none of your bindings use toInstance() , which will of course always return that pre-constructed instance in all cases and is effectively a singleton binding. 此外,请确保没有任何绑定使用toInstance() ,它当然总是在所有情况下都返回该预先构造的实例,并且实际上是单例绑定。

We had a case where we'd refactored out a bindView method and eventually forgot that we'd set it up to always bind its argument as a singleton (such that the view's parent container and view's controller could inject the same view). 我们遇到了一个案例,我们重构了bindView方法,最终忘记了将其设置为始终将其参数绑定为单例(这样,视图的父容器和视图的控制器可以注入同一视图)。

Barring that, as Danyel alluded to, there is circular dependency detection coded into Guice, and since you are calling your provider.get() within a @Inject -annotated method, you may be invoking it. 除非Danyel暗示过,否则Guice中编码了循环依赖项检测 ,并且由于您正在@Inject注释方法中调用provider.get() ,因此您可能正在调用它。

If you look inside Guice's source code, it will be clear what is actually done: 如果您查看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]);
    }
}

Apparently, when your object is injected, Guice stores it in that ThreadLocal variable. 显然,注入对象时,Guice将其存储在该ThreadLocal变量中。 Now, this according to this code snippet, it will instantly be released as it is injected. 现在,根据此代码片段,它将在注入时立即释放。 So, probably in your "scope" it is initialized somewhere else, probably at the beginning of the injection - and at the end of the injection, it is released. 因此,可能在您的“作用域”中将其初始化为其他位置,可能是在注入开始时-在注入结束时被释放了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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