我有以下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(...)
不是必需的。
答案 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")绑定不会。
但是,根据上面的示例,当参数包含在提供程序方法中时,它会立即在同一个侦听器上注册。您能否制作一个简短的自包含示例,以显示您所询问的行为?