Replied on the issue.
On Tue, Feb 5, 2013 at 12:28 PM, Aleksey Didik <[email protected]>wrote: > 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. > > > -- 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.
