bineanzhou / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Support mixed injection and manual wiring #231

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
There are cases where you want most members injected in a given class and
then to do some manual wiring (you may have a couple different bindings
that are wired slightly differently). Right now, it's an all or nothing
proposition.

For a class FooImpl, I should be able to bind a provider to FooImpl, and in
the provider, I should be able to get an injected instance of FooImpl that
I can further work on and return.

Original issue reported on code.google.com by crazybob...@gmail.com on 7 Aug 2008 at 12:57

GoogleCodeExporter commented 9 years ago
We discussed this today, and our best idea is to have an @New annotation (not a 
binding annotation) for provider 
methods, plus a toConstant() bind target.

Original comment by limpbizkit on 8 Aug 2008 at 1:44

GoogleCodeExporter commented 9 years ago
I mistyped: I meant a toConstructor() bind target.

Original comment by limpbizkit on 8 Aug 2008 at 1:46

GoogleCodeExporter commented 9 years ago
Just for clarification: Are you discussing 

1. a kind of post construction hook (which was also discussed in other issues 
and
could be realized using scopes), 
2. a solution for the so called robot-leg problem, that only needs one injector
(parent injector concept comes along with the "one injector per leg"-problem) 
3. or something completely different?

Original comment by sven.lin...@gmail.com on 8 Aug 2008 at 3:06

GoogleCodeExporter commented 9 years ago
Plan:
We'll Introduce a special binding annotation called '@New'. It is an error to 
bind to @New by hand; ie. it's an 
error to do this:
  bind(Foo.class).annotatedWith(New.class).to(...) 
When an injection point asks for an @New Foo, we create a default binding for 
the constructor of Foo. Foo 
must always be a concrete class with a Guice-invokable constructor (ie. @Inject 
or public no-args).

Complications:
What happens if Foo.class is annotated @Singleton? Do I get the same instance 
each time I inject @New Foo? 
Or different ones?
Suppose I inject both Foo and @New Foo. If Foo.class is annotaed @Singleton, do 
I get the same instance?

SPI Considerations:
I'm tempted to make it so @New is 1:1 with constructor bindings. For example, 
given this code:
   bind(Bar.class).to(BarImpl.class);
Guice would create 3 bindings:
   Bar.class linked to BarImpl.class (explicit)
   BarImpl.class linked to @New BarImpl.class (default)
   @New BarImpl to its own constructor (built-in)

Syntactic Sugar:
We confound linked bindings and constructor bindings in the current Guice. It 
means you can't solve the 
turkey bacon problem [http://tinyurl.com/turkeybaconproblem]. So I'd like to 
introduce some syntactic sugar 
related to @New:
  bind(Bar.class).toConstructor(BarImpl.class);
     is syntactic sugar for:
  bind(Bar.class).to(Key.get(BarImpl.class, New.class));

Original comment by limpbizkit on 28 Nov 2008 at 7:30

GoogleCodeExporter commented 9 years ago
Deferred to the next release so we can work out the scoping issues.

Original comment by limpbizkit on 25 Dec 2008 at 4:30

GoogleCodeExporter commented 9 years ago
We've implemented toConstructor() bindings:
  bind(Foo.class).toConstructor(Foo.class.getConstructor(Bar.class, Baz.class));

It's possible to easily implement @New as a simple built-in JIT binding on top 
of the toConstructor support.

Original comment by limpbizkit on 21 Jun 2009 at 6:21

GoogleCodeExporter commented 9 years ago
Issue 485 has been merged into this issue.

Original comment by sberlin on 23 May 2010 at 12:26

GoogleCodeExporter commented 9 years ago
toConstructor itself solves the TurkeyBacon problem as described @
http://tinyurl.com/turkeybaconproblem .  It would be solved by doing:

public class BritishModule extends AbstractModule {
  public void configure() {
    bind(Bacon.class).to(UncookedBacon.class);
    bind(Bacon.class).annotatedWith(Names.named("Turkey").to(TurkeyBacon.class);

bind(Bacon.class).annotatedWith(Names.named("Cooked")).toConstructor((Constructo
r)InjectionPoint.forConstructorOf(Bacon.class).getMember());
  }
}

.. a little bit unwieldy code-wise, but it works.

Is @New still needed?  It can be worked around pretty easily by:

bind(Bar.class).annotatedWith(named("new")).toConstructor((Constructor)Injection
Point.forConstructorOf(BarImpl.class).getMember());
and later using it was @Inject Baz(@Named("new") Bar bar) { ... }

In other words, instead of toConstructor being syntactic sugar for @New, @New 
would
be syntactic sugar for toConstructor.

It'd be pretty easy to hack up, either way.

Original comment by sberlin on 23 May 2010 at 2:21

GoogleCodeExporter commented 9 years ago
FYI - I committed a test in r1166 that asserts that toConstructor solves the
turkeybacon problem.

Original comment by sberlin on 23 May 2010 at 2:32

GoogleCodeExporter commented 9 years ago
Thinking about this some more... it looks like attempts to introduce @New would
introduce a lot confusion.  For example, if Bar is linked to BarImpl.class, what
would "@New Bar" return?  What if Bar was linked to Provider<Bar>, or @Provides 
Bar.
 Would @New just be disallowed on interfaces because of that confusion?  

I think we're safest adding an easy-to-use "find the right constuctor" method,
something like <T> Constructor<T> Constructors.forConstructorOf(Class<T> 
clazz), to
reduce the boilerplate from comment #8 of using InjectionPoint to find the right
constructor.  Then users can use it to create their own "new" bindings, 
annotated
with whatever they'd like.  That way, things like "@New Bar" would be defined,
because the user would have had to define it.

I'm for closing this as "will not fix" -- please chime in if you think 
otherwise!

Original comment by sberlin on 23 May 2010 at 3:18

GoogleCodeExporter commented 9 years ago
Closing as fixed because toConstructor allows this with some configuration 
(bind your object with toConstructor and a custom @New annotation).

Original comment by sberlin on 25 Oct 2010 at 12:15