Pass parameter to constructor with Guice

If this class is a factory, it should be a Guice-managed object, having a non static getFoo method, and the getFoo method would just use

new Foo(bar)

Not every class needs to be instantiated by Guice.

Also see AssistedInject, to avoid creating this factory yourself and let Guice create one for you.


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


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.


I know that this is old thread but I just hit the issue myself today. I only need two or maximum three different instances of 'Foo' and I really didn't want to write all the bolierplate code of Factory. With a little googling I found this Stubbisms – Tony’s Weblog I would suggest this solution which is perfect if you know exactly what instances you need.

In Guice module:

    bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic A");
        }
    });
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(new Provider<Foo>() {
        @Override
        public Foo get() {
            return new FooImpl("topic B");
        }
    });

Or in java 8:

    bind(Foo.class).annotatedWith(Names.named("firstFoo")).toProvider(() -> new FooImpl("first"));
    bind(Foo.class).annotatedWith(Names.named("secondFoo")).toProvider(() -> new FooImpl("second"));

And in constructor of your service where you need Foo instances:

@Inject
public MyService (
    @Named("firstFoo") Foo firstFoo,
    @Named("secondFoo") Foo secondFoo) {
}

And Foo in my case:

public class FooImpl implements Foo {

    private String name;

    public FooImpl(String name) {
        this.name = name;
    }

    @Override
    public String getName() {
        return name;
    }
}

Hope it helps someone.