1

私はguice3と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を返します。しかし、そうではないはずです。

私は何が間違っているのですか?

4

2 に答える 2

1

あなたはすでにこれをチェックしているかもしれません-あなたが使用する「種類の」バインディングをリストしました-しかし、編集されていないコードでは、関連するクラスのどれもスコープで慎重に注釈付けされ@Singletonたりバインドされていないことを再確認する価値があります。Singleton.classさらに、どのバインディングも を使用しないようにしてくださいtoInstance()。これはもちろん、すべての場合に事前に構築されたインスタンスを常に返し、事実上シングルトン バインディングです。

メソッドをリファクタリングして、bindViewその引数を常にシングルトンとしてバインドするように設定したことを最終的に忘れてしまったケースがありました (ビューの親コンテナーとビューのコントローラーが同じビューを挿入できるようにするため)。

Danyelがほのめかしたように、Guiceにコード化された循環依存関係検出があり、 -annotatedメソッドprovider.get()内で呼び出しているため、それを呼び出している可能性があります。@Inject

于 2013-02-07T17:04:21.023 に答える
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変数に格納します。さて、これはこのコード スニペットによると、注入されるとすぐに解放されます。したがって、おそらくあなたの「スコープ」では、おそらく注入の開始時にどこかで初期化され、注入の最後に解放されます。

于 2013-02-07T17:34:02.040 に答える