Question

I'm fairly new to Guice so hopefully this isn't an obvious question...

I'm dealing with a framework which dynamically instantiates one of my application classes (let's call it C) using reflection, so I have no control over its instantiation. Furthermore, there is no easy way for me to access a newly created C after the framework has instantitated it. HEre's what C would look like:

    public class C implements I {

        public C() {
            // this ctor is invoked by the framework so can't use DI here?
        }        

        public void initialize() {
            // this is a post instantiation hook which the f/w will invoke
        }

        private void m() {
            Dependency d = Dependency.getInstance();
            d.doSmth();
        }
    }

I would like C to acquire Dependency using DI. Here Dependency is clearly a singleton but this needn't be the case generally.

I have come up with two possible solutions, neither of which feels very tidy, so I thought I'd ask the experts:

  1. Static injection. I struggle to see how this improves drastically over the service locator anti-pattern though - I end up with non final static fields which could be manipulated externally... hmmm.

  2. The framework supports a hook for C to initialize itself post instantiation (the initialize() method shown above). This method could self-inject the newly created instance using setter injection.

With 2, I guess this means more external alterability but at least exposes the dependency a little more explicitly for things like unit tests. Trouble is: how do I get my hands on the Guice Injector in that case (short of relying on yet another service locator)? I've also read (and tend to agree with) that explicitly referring to the Injector throughout app code is dubious practice.

Your insight would be really appreciated.

Many thanks,
Christian

Was it helpful?

Solution

You could try statically injecting providers into C. Static injection more awkward to test. But the providers make it possible for Guice to validate your dependencies eagerly, while creating them lazily.

public class C implements I {
  @Inject static Provider<Dep1> dep1Provider;
  @Inject static Provider<Dep2> dep2Provider;

  ...

  public void initialize() {
    Dep1 dep1 = dep1Provider.get();
    Dep2 dep2 = dep2Provider.get();
    ...
  }
}

OTHER TIPS

If you make your Guice injector available by static variable and static accessor methods you can solve it like this:

public class C implements I {

    public C() {
        // this ctor is invoked by the framework, you can't do injection here.
    }        

    public void initialize() {
        MyGuice.getInjector().inject(this);
    }

    @Inject
    protected void init(Dep1 dep1, Dep2 dep2) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    private void m() {
        dept1.doSmth();
    }
}

The static call is a bit of an anti-pattern, you could remove that dependency with a simple annotation that takes care of the post constructor injection if you are willing to use a solution that does code weaving or a post compile step. This way you can inject all objects even if they don't have an initialize method. You can find an example of this here: How to inject model object with AspectJ.

@Configurable
public class C implements I {

    public C() {
        // this ctor is invoked by the framework, you can't do injection here.
    }        

    @Inject
    protected void init(Dep1 dep1, Dep2 dep2) {
        this.dep1 = dep1;
        this.dep2 = dep2;
    }

    private void m() {
        dept1.doSmth();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top