Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass parameter to constructor with Guice

I have a factory as below,

public final class Application {      private static IFoo foo;      public static IFoo getFoo(String bar)     {         // i need to inject bar to the constructor of Foo         // obvious i have to do something, not sure what         Injector injector = Guice.createInjector();         logger = injector.getInstance(Foo.class);         return logger;                   }  } 

This is the Foo definition:

class Foo {    Foo(String bar)    {     }  } 

OK. I m not sure how I can pass this parameter to Foo constructor with Guice?

Any ideas?

like image 525
DarthVader Avatar asked Feb 11 '12 05:02

DarthVader


People also ask

What does @inject do Guice?

Note that the only Guice-specific code in the above is the @Inject annotation. This annotation marks an injection point. Guice will attempt to reconcile the dependencies implied by the annotated constructor, method, or field.

What is @named annotation in Guice?

Guice comes with a built-in binding annotation @Named that takes a string: public class RealBillingService implements BillingService { @Inject public RealBillingService(@Named("Checkout") CreditCardProcessor processor, TransactionLog transactionLog) { ... }

What is @inject annotation in Guice?

Annotation Type Inject. @Target(value={METHOD,CONSTRUCTOR,FIELD}) @Retention(value=RUNTIME) @Documented public @interface Inject. Annotates members of your implementation class (constructors, methods and fields) into which the Injector should inject values.

What does bind do in Guice?

Binding is to Guice as wiring is to Spring. With bindings, we define how Guice is going to inject dependencies into a class. This module implementation specifies that an instance of DefaultCommunicatorImpl is to be injected wherever a Communicator variable is found.


2 Answers

All the "Guice Constructor Parameter" answers seem to be incomplete in some way. Here is a complete solution, including usage and a visual:

enter image description here

interface FooInterface {     String getFooName(); } 

// Annotate the constructor and assisted parameters on the implementation class

class Foo implements FooInterface {     String bar;      @Inject     Foo(@Assisted String bar) {         this.bar = bar;     }      // return the final name     public String getFooName() {         return this.bar;     }  } 

// Create a factory interface with a create() method that takes only the assisted parameters.

// FooFactory interface doesn't have an explicit implementation class (Guice Magic)

interface FooFactory {     Foo create(String bar); } 

// Bind that factory to a provider created by AssistedInject

class BinderModule implements Module {      public void configure(Binder binder) {         binder.install(new FactoryModuleBuilder()                 .implement(FooInterface.class, Foo.class)                 .build(FooFactory.class));     } } 

// Now use it:

class FooAction {     @Inject private FooFactory fooFactory;      public String doFoo() {         // Send bar details through the Factory, not the "injector"         Foo f = fooFactory.create("This foo is named bar. How lovely!");         return f.getFooName(); // "This foo is named bar. How lovely!"     } } 

Lots of helps here: https://google.github.io/guice/api-docs/latest/javadoc/index.html?com/google/inject/assistedinject/FactoryModuleBuilder.html

like image 193
DougA Avatar answered Sep 20 '22 11:09

DougA


What you are probably looking for is to use a Guice factory. Particularly easy with the AssistedInject functionality, but they have a manual example at the top of the page. The short of it for the manual example is that you get the factory under non-static getFoo method that you pass whatever parameters to that you need and build the object from there.

This won't work directly if you have method interception in Foo, but it will work in many other cases.

To use AssistedInject, which to me has somewhat cleaner semantics and means less manual wiring, you'll need the guice-assistedinject extension in the classpath, then when creating Foo (well, FooImpl, we should be using interfaces):

@Inject public FooImpl(@Assisted String bar) {     this.baz = bar; } 

Then you create a FooFactory interface:

public interface FooFactory {     public Foo create(String bar); } 

Then in your guice module:

install(new FactoryModuleBuilder()     .implement(Foo.class, FooImpl.class)     .build(FooFactory.class)); 

You can check out the javadoc for FactoryModuleBuilder for examples with more complex factories.

like image 45
David H. Clements Avatar answered Sep 18 '22 11:09

David H. Clements