Search code examples
javadependency-injectionguice

Google Guice Depedency Injection - Where exactly the object is created?


I have the below code in which i dont understand where exactly the new instance of EmailService is created. I tried to check many other stackoverflow conversations, but still couldnt get it clearly.

public interface MessageService {
    void sendMessage(String msg, String recipient);
}

@Singleton
public class EmailService implements MessageService {

    @Override
    public void sendMessage(String msg, String recipient) {
        System.out.println("Sending Email to"+recipient+"Msg is:" + msg);
    }
}

public class MyApplication {
    private MessageService service;

    @Inject
    public MyApplication(MessageService service) {
      this.service = service;
    }

    public void sendMessage(String msg, String recipient) {
        this.service.sendMessage(msg, recipient);
    }
}

public class AppInjector extends AbstractModule {

    @Override
    protected void configure() {
      bind(MessageService.class).to(EmailService.class);
    }

}

public class ClientApplication {
    public static void main(String[] args) {
        Injector inj = Guice.createInjector(new AppInjector());
        MyApplication app = inj.getInstance(MyApplication.class);
        app.sendMessage("How are you?", "hello@hello.com");
    }
}

nowhere in this code, new instance of class EmailService is created something like (new EmailService()).


Solution

    1. Via reflection Guice analyzes MyApplication's constructor and finds out that it depends on MessageService (public MyApplication(MessageService service)). Exactly this constructor is taken because it is marked with @Inject
    2. Guice tries to find out binding for this interface. In AppInjector you specified that implementation for MessageService is EmailService (bind(MessageService.class).to(EmailService.class);)
    3. EmailService is instantiated via Java Reflection API. It is done via Class.newInstance
    4. After EmailService is created, it is passed as a parameter to MyApplication.class.newInstance() factory.

    Notes:

    • By default, if you have not specified any additional constructor, there is a default one without parameters, that's why EmailService has not dependencies.
    • EmailService instance is a singleton because it is marked with @Singleton, so if there will be more dependencies on it, exactly the same instance will be injected
    • If you would like to create binding to instance, you can use the following code: bind(MessageService.class).toInstance(new EmailService());
    • Google libraries are always rich in terms of documentation. I advice you to read through this wiki: google/guice/wiki