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

我究竟做错了什么?

最佳答案

如果您查看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变量中。现在,根据此代码片段,它将在注入时立即释放。因此,可能在您的“作用域”中将其初始化为其他位置,可能是在注射开始时-在注射结束时将其释放。

关于java - guice-提供者总是返回相同的实例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14748442/

10-11 22:28