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() {...});    
}

我知道Untargetted 绑定和声明:

非目标绑定会通知注入器类型,因此它可能会急切地准备依赖项。

我仍然希望 GuiceTypeListener为任何第一次显式绑定注入的类型调用。

那么我是否需要根据经验为此类类进行非目标绑定?

注意: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 回答