Guice TypeListener not notified about the injected class Type
I have the following Guice module:
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
...
}
}
What I found strange is that my TypeListener
doesn't get notified about the Parameter
type. Even though the provider is beign called and returns SomeClass
. I also see the log statement so clearly the Parameter
was injected by Guice.
@Override
protected void configure() {
bind(Parameter.class);
bindListener(Matchers.any(), new TypeListener() {...});
}
I'm aware of Untargetted bindings and the statement:
An untargetted binding informs the injector about a type, so it may prepare dependencies eagerly.
I would still expect Guice to call the TypeListener
for any type which is either explicitly binded or injected for the first time.
So do I need to make untargetted binding for such classes as a rule of thumb?
NOTE: marking the Parameter
constructor with @Inject
doesn't solve the problem.
EDIT:
The complete example (hope I din't leave too much garbage) is as follows:
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");
}
}
}
If the line is present the output is:
Type: class com.barcap.test.TestGuice$SampleInjectedClass
Type: class com.google.inject.internal.ProviderMethod
Test
If I remove the line I get:
Type: class com.google.inject.internal.ProviderMethod
Test
I noticed that if the injector wasn't created via the createChildInjector
code the bind(...)
is not necessary.
Just-in-time bindings created for child injectors will be created in an ancestor injector whenever possible. This means that, without the bind(SampleInjectedClass.class);
line, the binding for SampleInjectedClass
is created in the parent injector. Since the parent injector doesn't have your TypeListener
, it won't be triggered.
Can you check your code? In my test on Guice 3, I couldn't reproduce what you're seeing.
Also, from the TypeListener docs, emphasis mine and typo sic:
public abstract void hear (TypeLiteral<I> type, TypeEncounter<I> encounter)
Invoked when Guice encounters a new type eligible for constructor or members injection. Called during injector creation (or afterwords if Guice encounters a type at run time and creates a JIT binding) .
Though all the rest of your dependencies will be called on the TypeListener immediately when the injector is created, implicit ("just-in-time") bindings will not.
However, based on my example above, it appears that when a parameter is included in a provider method, it is registered on the same listener immediately. Can you produce a short self-contained example that shows the behavior you're asking about?
链接地址: http://www.djcxy.com/p/16932.html上一篇: 将现有的列转换为标识