【问题标题】:Guice TypeListener not notified about the injected class TypeGuice TypeListener 未通知注入的类 Type
【发布时间】:2013-11-04 09:43:04
【问题描述】:

我有以下 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

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

注意:@Inject 标记Parameter 构造函数并不能解决问题。

编辑:

完整的例子(希望不要留下太多垃圾)如下:

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(...)

【问题讨论】:

  • 给定的代码不足以重现问题。我没有看到发布的代码有什么特别的问题,你怎么知道没有调用 TypeListener?
  • 请看附件的完整示例
  • 好的,现在我明白发生了什么。

标签: java guice


【解决方案1】:

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

【讨论】:

  • 但是,如果您调用bind(SampleInjectedClass.class).asEagerSingleton(),将创建绑定并触发您的TypeListener
【解决方案2】:

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

另外,来自TypeListener docs,强调我的和错字原文:

public abstract void hear (TypeLiteral&lt;I&gt; type, TypeEncounter&lt;I&gt; encounter)

当 Guice 遇到适合构造函数或成员注入的新类型时调用。在注入器创建期间调用(如果 Guice 在运行时遇到类型并创建 JIT 绑定,则在后面调用)

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

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

【讨论】:

  • 会试试的。我试图从更复杂的示例中提取重要部分,很可能我明显遗漏了一些东西。一件重要的事情可能是我使用的是childInjector。将按照建议提取示例并返回。
猜你喜欢
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-13
相关资源
最近更新 更多