5

What is your advice?

I found most suitable for me solution - keep injectors and modules in enumeration classes. Advantages:

  1. injectors and modules created once,
  2. injectors can be used from different classes while running application (not only at bootstrap),
  3. injectors kept in one place and can be easily found.

Example:

import static ru.package.Modules.*;

public enum Injectors {

FOO_INJECTOR(BarModule.module()),

FOO2_INJECTOR(FOO_INJECTOR.injector(),
        Bar2Module.module(), FooModule.module());

private final Injector m_injector;

Injectors (Module... modules) {
    m_injector = Guice.createInjector(modules);
}

Injectors (Injector parentInjector, Module... modules) {
    m_injector = parentInjector.createChildInjector(modules);
}

public Injector injector() {
    return m_injector;
}
}
Alex M
  • 395
  • 1
  • 4
  • 6
  • 8
    Do not do this. This strategy has many problems. In every execution of your program all of your injectors will be created, whether they're needed or not. – Jesse Wilson Feb 01 '10 at 15:59

2 Answers2

17

You appear to be fundamentally misunderstanding how dependency injection works. If you are trying to use a reference to Injector anywhere in your code besides the place where you bootstrap the application, you're not using dependency injection, you're using it as a Service Locator instead. You're forced to prepare an Injector whenever you need to test a class and your classes do not make it clear in their constructors exactly what their dependencies are (since who knows what they'll get out of the Injector in some method if they have or can get a reference to it). Actually, using enum as you've described here is even worse than that: you cannot change the configuration at all, even for testing, because your modules are hardcoded into the enum.

With dependency injection, classes declare their dependencies only and allow the Injector, working transparently (after the initial call to get the root application object), to provide all those dependencies. This makes understanding, testing and changing functionality in your code relatively easy. Anyway, I'd suggest learning more about how DI and Guice are intended to be used... you really should not want to do this.

ColinD
  • 108,630
  • 30
  • 201
  • 202
  • I'm new to DI and Guice, so plz be patient ) 1) It's used in web application, so i need to allocate objects with all dependency graph at runtime, not only at bootstrap. 2) Enum. You shouldn't change modules every time you want to test. For test you can configure separate modules and injectors (if it is needed) . 3) And why i must use injector only for root objects? What about, for instance, AOP? – Alex M Feb 02 '10 at 08:01
  • @ColinD I have a similar need for the injector because I do not just need to do DI during construction, but would also like to be able to access the Singleton instances during runtime (via Beanshell for runtime debugging purposes etc.). In other words, I would need some sort of registry for the singletons. Now, without DI, we would usually use a static final field to hold it, but now with Guice DI, the injector seems to be the natural choice for the registry. – RAY Nov 06 '12 at 04:11
  • 1
    Consider legacy applications in which it may not be practical to apply dependency injection everywhere in the dependency graph right away. As you attempt to introduce dependence injection little by little, you end up with some uses of the injector as a service locator, strategically placed. – beluchin Mar 28 '14 at 20:51
  • @beluchin: That's reasonable, provided that you first understand the way that dependency injection is intended to be used and use it that way when possible. – ColinD Mar 28 '14 at 20:53
6

The bigger question is why?

There should be no need to keep the Injector around, because once the injection is done the Injector should be done and should disappear.

If, however, you really need the Injector, couldn't you simply:

@Inject
private Injector injector;

Is this application web based or is it standalone?

gpampara
  • 11,989
  • 3
  • 27
  • 26
  • This code is used in web also, but not only. About injecting the Injector i asked already question: http://stackoverflow.com/questions/2176216/how-to-inject-injector. The problem is that guice doesn't allow to bind or provide Injector. – Alex M Feb 01 '10 at 12:08
  • I have to agree with ColinD, it might be useful to understand how DI works. It's gonna save you a lot of time and effort :) – gpampara Feb 02 '10 at 05:38