Guice inject injector or generic provider somehow

dependency-injection, generics, guice, inversion-of-control, java

Solution

This may not be the best solution, but it could work for you.

You can implement a Provider that allows you to supply the dynamic input. Then have that Provider injected into the classes that need them so you can create your the object you need dynamically.

Here's a snippet from the Provider JavaDoc:

An implementation class may always choose to have a Provider instance injected, rather than having a T injected directly. This may give you access to multiple instances, instances you wish to safely mutate and discard, instances which are out of scope (e.g. using a @RequestScoped object from within a @SessionScoped object), or instances that will be initialized lazily.

It could look something like the following. I personally think it's fine to inject the Injector into a provider because it's part of the injection framework. The goal is to keep the Injector out of your application code, and this certainly does.

public class FooProvider implements Provider<Foo>

    @Inject
    private Injector injector;

    private String input;

    public void setInput(String input){
        this.input = input;
    }

    @Override
    public Foo get(){
        if(input.equals("bar")){
            injector.getInstance(Bar.class); // Bar implements Foo
        }
        else{
            injector.getInstance(Baz.class; // Baz implements Foo
        }
    }
}

Then elsewhere...

public class Goo{

    @Inject
    Provider<Foo> fooProvider;

    public Foo goo(String input){
        fooProvider.setInput(input);
        return fooProvider.get();
    }
}

The key is to make sure each provider instance is unique per injection point, which I think it is by default. Since this provider has mutable state, you cannot have this being thrown around your application (and potentially doing the wrong thing in a multi-threaded environment) unless that is what you intend on it doing. Then you will need to take more precautions.

Problem

I need to have lazyload logic for creating mappers in my class. Each mapper Inherited from `Mapper<T>` interface. But through the time object working it could use multiple mappers depending from input it handling. As I see it's not a good way to inject injector in class, but how could I implement lazyload do not doing that? I cant use `Provider<Mapper>` because provider have no options to determine which exact mapper I need at time. Thanks a lot.

Original source