You are thinking incorrectly about dependency injection. Dependency injection and a service locator are mirror images of each other: using a service locator, you request it for an object. When injecting dependencies, you are not looking for dependencies, they are simply passed on to you.
Basically, "it's turtles all the way down!" Each dependency of your class must be introduced. If MyApplication needs a MyConfiguration object, it should just accept the MyConfiguration object as a constructor parameter and not worry about how it was created.
Now, this does not mean that you can never use new manually, but you should reserve this for objects of type value that have no external dependencies. (And in these cases, I would say that you are often better off using a static factory method than a public constructor, but that is not the case.)
Now there are several ways to do this. One way is to trick MyConfiguration many tiny pieces so that instead of myConfiguration.getConfig("x") you would do an @Inject @Configuration("x") String or something like that. Alternatively, you can make MyConfiguration itself injectable, and then provide methods for accessing them for fragments for it. The correct answer to some extent depends on the type of data you are trying to model - too dependent on dependencies, and your bindings can be difficult to maintain (although there are ways to do this better); make the dependencies too coarse, and it becomes harder for you to test (for example: which is easier by providing only the “x” configuration that the tested class requires, or building the entire application configuration?).
You can do both:
@BindingAnnotation @Retention(RetentionPolicy.RUNTIME) public @interface Config { String value(); } final class MyConfigurationModule extends AbstractModule { @Override protected void configure() {} @Provides @Singleton MyConfiguration provideMyConfiguration() {
In unit tests, you can use a similar approach:
@RunWith(JUnit4.class) public final class MyApplicationTest {
Dependency injection also encourages another best practice, which I highly recommend, which is to develop your type system so that invalid states cannot be represented (as much as possible). If the entire MyApplication configuration needs to be passed in its constructor, it will never have a MyApplication object that does not have the correct configuration. This allows you to “load” your class invariants, which greatly facilitates the discussion of the behavior of your objects.
Finally, a note on Injector.getInstance() . Ideally, you use Injector exactly once in your program: immediately after creating it. That is, you should be able to do Guice.createInjector(...).getInstance(MyApplication.class).start() and never store the link to Injector anywhere. I tend to create applications using the Guava ServiceManager abstraction (see also this question ), so the only thing I need to do is:
public static void main(String[] args) throws Exception { Injector injector = Guice.createInjector(...); ServiceManager manager = injector.getInstance(ServiceManager.class); manager.startAsync().awaitHealthy(); }