8

次の Guice モジュールがあります。

class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        bindListener(Matchers.any(), new TypeListener() {...});    
    }

    @Provides
    SomeClass createSomeClass(final Parameter param) {
        log(param.getValue()); <-- this gets logged
        ...
    }
}

私が奇妙だと思ったのは、タイプTypeListenerについて通知されないことです。Parameterプロバイダーが呼び出されて返されますがSomeClass。ログ ステートメントも表示されるのでParameter、Guice によって注入されたことがはっきりとわかります。

@Override
protected void configure() {
    bind(Parameter.class);
    bindListener(Matchers.any(), new TypeListener() {...});    
}

Untargeted bindingsと次のステートメントを認識しています。

対象外のバインディングはインジェクターに型について通知するため、依存関係を熱心に準備できます。

TypeListener明示的にバインドされた、または初めて注入された型に対して Guiceが呼び出すことを期待します。

経験則として、そのようなクラスに対して非対象バインディングを作成する必要がありますか?

注:Parameterコンストラクターを でマークして@Injectも問題は解決しません。

編集:

完全な例 (あまりにも多くのゴミを残さないことを願っています) は次のとおりです。

public class TestGuice {

    public static void main(String[] args) {
        Injector parentInjector = Guice.createInjector(new ParentModule());
        Injector childInjector = parentInjector.createChildInjector(new SubModule());

        childInjector.getInstance(Runnable.class).run();
    }

    static class ParentModule extends AbstractModule {

        @Override
        protected void configure() {

        }
    }

    static class SubModule extends  AbstractModule {

        @Override
        protected void configure() {
            bind(SampleInjectedClass.class); // <-- Comment/uncomment here

            final TypeListener typeListener = new TypeListener() {
                public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter) {
                    System.out.println("Type: " + type.getRawType());
                }
            };

            bindListener(Matchers.any(), typeListener);
        }

        @Provides
        Runnable createRunnable(final SampleInjectedClass sampleClass) {
            return new Runnable() {

                @Override
                public void run() {
                    sampleClass.test();
                }
            };
        }
    }

    static class SampleInjectedClass {
        public void test() {
            System.out.println("Test");
        }
    }
}

行が存在する場合、出力は次のようになります。

タイプ: クラス com.barcap.test.TestGuice$SampleInjectedClass

タイプ: クラス com.google.inject.internal.ProviderMethod

テスト

行を削除すると、次のようになります。

タイプ: クラス com.google.inject.internal.ProviderMethod

テスト

createChildInjectorインジェクターがコードを介して作成されていない場合、必要ないことに気付きましたbind(...)

4

2 に答える 2

3

子インジェクター用に作成されたジャストインタイム バインディングは、可能な限り祖先インジェクターで作成されます。これは、bind(SampleInjectedClass.class);行がなければ、バインディングSampleInjectedClassが親インジェクターで作成されることを意味します。親インジェクターにはあなたTypeListenerの がないため、トリガーされません。

于 2013-10-29T23:31:38.083 に答える
0

コードを確認できますか?Guice 3 での私のテストでは、あなたが見ているものを再現できませんでした。

また、TypeListener docsから、鉱山とタイプミスを強調します。

public abstract void hear (TypeLiteral<I> type, TypeEncounter<I> encounter)

Guice がコンストラクターまたはメンバーの注入に適した新しい型に遭遇したときに呼び出されます。インジェクターの作成中に呼び出されます (Guice が実行時に型に遭遇し、JIT バインディングを作成する場合は、あとがき)

残りのすべての依存関係は、インジェクターが作成されるとすぐに TypeListener で呼び出されますが、暗黙的な (「ジャストインタイム」)バインディングは呼び出されません。

ただし、上記の例に基づくと、パラメーターがプロバイダー メソッドに含まれている場合、パラメーターはすぐに同じリスナーに登録されるようです。あなたが求めている動作を示す短い自己完結型の例を作成できますか?

于 2013-10-25T17:11:38.940 に答える