Taking a look at Guice (and Dagger) for a new project. Every Guice tutorial I have seen so far shows an injector being created at the point where the developer needs the DI to create an object instance.
A typical example seen on the web:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BasicModule());
Communication comms = injector.getInstance(Communication.class);
}
To me this defeats the purpose of the DI - everywhere an instance is required, you tie the instance to the modules which define how to build it.
Is there a way to ask Guice to create an instance of a class who's module (dependency graph) has been previously defined to Guice (eg. at application startup?).
I am using the Dropwizard.io framework so there are situations where I don't have full control over the way a class is constructed but want to be able to mock out the dependencies I reference in that class.
Exactly the same applies to Dagger - I'd appreciate examples for either/both.
Edit: I've worked with several DI frameworks in .NET over the years, so I'm going to give an example of what I'm trying to do based on one of those.
For example, in the ASP.NET Core DI implementation, at service start-up you define the services you want the DI to be able to create. Typically you'll be asking the DI to give you an instance which is an implementation of an interface. So at start-up:
protected override void ConfigureAdditionalServices(IServiceCollection services)
{
services.AddScoped<ITransactionService, TransactionService>();
}
where IServiceCollection
is the collection of services defined to the DI.
Because the DI is integrated with the ASP.NET framework, from this point on you can generally define a constructor which takes ITransactionService
and the DI will provide it for you.
However, if you were using the DI in a framework which did not know about it, you'd need access to the current ServiceProvider instance, and then you could ask the DI to create your object like this:
var transactionService = ServiceProvider.GetService<ITransactionService>();
I realise that this implemeting the Service Locator anti-pattern but it still has the benefit of decoupling my code from the concrete class implementations and allowing me to mock them out for testing at application start-up.
So back to the question So to restate my question in the light of this context, how can I request a class from Guice at some random point in my code?
What would I need to change in this code to make it work?
public class TransactionModule extends AbstractModule {
@Override
protected void configure() {
bind(TransactionServiceBase.class).to(TransactionService.class);
}
}
// At startup
Injector injector = Guice.createInjector(new TransactionModule());
// Then, somewhere in the application, to get an instance of TransactionService
TransactionServiceBase transactionService = (TransactionServiceBase)Guice.getInstance(TransactionServiceBase.class);