Guice TypeListener未通知注入的类Type

时间:2013-10-25 10:11:55

标签: java guice

我有以下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 bindings和声明:

  

一个无法解决的绑定通知注入器有关类型的信息,因此它可能会急切地准备依赖关系。

我仍然希望Guice为第一次明确绑定注入的任何类型调用TypeListener

那么我是否需要根据经验对这些类进行无限制的绑定?

注意: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");
        }
    }
}

如果该行存在,则输出为:

  

输入:class com.barcap.test.TestGuice $ SampleInjectedClass

     

输入:class com.google.inject.internal.ProviderMethod

     

测试

如果我删除了我得到的行:

  

输入:class com.google.inject.internal.ProviderMethod

     

测试

我注意到如果没有通过createChildInjector代码创建注入器,则bind(...)不是必需的。

2 个答案:

答案 0 :(得分:3)

Just-in-time bindings created for child injectors will be created in an ancestor injector whenever possible。这意味着,如果没有bind(SampleInjectedClass.class);行,则会在父注入器中创建SampleInjectedClass的绑定。由于父注入器没有TypeListener,因此不会触发它。

答案 1 :(得分:0)

你能查一下你的代码吗?在我对Guice 3的测试中,I couldn't reproduce what you're seeing

另外,从TypeListener docs开始,强调我的错误和错误:

  

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

     

当Guice遇到符合构造函数或成员注入条件的新类型时调用。在注入器创建过程中调用(如果Guice在运行时遇到类型并创建JIT绑定,则为后面文字)

虽然在创建注入器时会立即在TypeListener上调用所有其他依赖项,但implicit ("just-in-time")绑定不会。

但是,根据上面的示例,当参数包含在提供程序方法中时,它会立即在同一个侦听器上注册。您能否制作一个简短的自包含示例,以显示您所询问的行为?