Hi guys,
Today I recognized easy one tricky part of JIT binding based on *
TypeListeners* and *ChildInjectors* usage.
Let me explain step by step:
*First*
For every binding *bind(Foo.class).to(FooImpl.class)* one JIT binding will
be created. Binding for *FooImpl.class* implemented by *
ConstructorBindingImpl.class*.
As soon as *FooImpl.class* is not explicitly bind, it'll be bind
just-in-time. As it always happened with final implementations.
*Second*
Guice tried to create JIT binding in parent injector first. If it's not
possible then in would be created in a child.
Let's review the example. We have some base classes for binding:
class Dependency {} //just a dependency
interface Foo {} //interface for binding
class FooImpl implements Foo {} //base implementation without
dependencies
class EnhancedFooImpl implements Foo { //enhanced implementation with
dependency
@Inject
EnhancedFooImpl(Dependency dependency) {
}
}
Next, let's make injectors hierarchy: bind nothing in parent and bind our
classes in child.
Injector parentInjector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
//nothing here
}
});
parentInjector.createChildInjector(new AbstractModule() {
@Override
protected void configure() {
bind(Dependency.class);
bind(Foo.class).annotatedWith(Names.named("simple")).to(FooImpl.class);
bind(Foo.class).annotatedWith(Names.named("enhanced")).to(EnhancedFooImpl.class);
}
});
At the child injector initialization time, two just-in-time bindings will
be created: for *FooImpl.class *and* EnhancedFooImpl.class.*
But due to "JIT parent first strategy" *FooImpl.class *bindings* *will be
created by parent injector due to both classes have no dependencies at all.
As well as *EnhancedFooImpl.class* will be created by child injector, due
to dependency on binding from child injector space (*Dependency.class*).
That means, JIT binding will be created by injector which can resolve all
dependencies by himself.
*Tricky*
It's tricky because we don't know, what injector actually will build
implementation instance. Depends on implementation dependencies it can be
one from all injectors hierarchy.
And more, what about type listeners defined by child injector?
Let's add type listener for all classes in child injection:
Injector childInjector = parentInjector.createChildInjector(new
AbstractModule() {
@Override
protected void configure() {
bind(Dependency.class);
bind(Foo.class).annotatedWith(Names.named("simple")).to(FooImpl.class);
bind(Foo.class).annotatedWith(Names.named("enhanced")).to(EnhancedFooImpl.class);
//bind listener for all injections in this injector
bindListener(Matchers.any(), new TypeListener() {
@Override
public <I> void hear(TypeLiteral<I> type,
TypeEncounter<I> encounter) {
encounter.register(new InjectionListener<I>() {
@Override
public void afterInjection(I injectee) {
//this call was never happened for FooImpl
creation
//but will successfully called for
EnhancedFooImpl creation
}
});
}
});
}
});
Due to the fact FooImpl.class binding created by parent injector, injection
listener defined in the child injector would never called.
Parent injector just doesn't no about some injection listeners in child
containers :(
So behavior is not obvious. If we have a hierarchy of injector as well as
hierarchy of type listeners, we can't guarantee what of them will be
processed and what not. Depends on what level dependencies is enough to
create JIT binding for implementation class. I think it can create some
floating issues.
In addition, to reproduce the same effect, try to inject Injector
dependency in both implementation classes. For FooImpl.class it'll be
parent injector instance. For EnhancedFooImpl.class - child injector
instance.
I'm not sure, what happened if we will always create JIT binding in an
injector where binding will be requested.
P.S. Test attached.
Issue submitted: http://code.google.com/p/google-guice/issues/detail?id=740
*
*
--
You received this message because you are subscribed to the Google Groups
"google-guice" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-guice?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.