Radical Java

You probably don't need a dependency injection framework

It has probably been drilled into your head 100 times that dependency injection frameworks make you application easier to test, more reconfigurable, and less tempting to use global state. Whilst it sounds like a tempting proposition, it’s not always as sensible as it sounds.

Dependency injection frameworks work by inverting the control flow (“don’t call us, we’ll call you”), and setting up the dependencies between your application components automatically, rather than you doing it yourself. This seems to stem from an inate aversion to the new keyword, meaning that you’d rather have someone else use your constructors by reflection than having to call them yourself.

Guice and Spring are probably the most well-known of the DI frameworks for Java. Guice is a product of Google, and marginally more sensible in scope and implementation than Spring. Spring used to be, and still is to a certain extent, a running joke amongst Java developers for it’s over-reliance on XML configuration, possibily giving rise to the seasoned Java developer’s horror upon even hearing those dreaded 3 letters. The project has come to encompass so much more in recent years and is now attempting to be just about everything all at once.

Luckily some of the horrors of the early days of Spring IOC have gone away, so the basic modern concept is now this:

public class ApplicationTask {
    private final ServiceClient client;
    public ApplicationTask(@Inject ServiceClient client) {
        this.client = client;
    }

    public void run() {
        client.doSomething();
    }
}

/* ... */

public static void main(String[] args) {
    AppContext context = SomeDependencyFramework.setup(/* Some configuration mechanism here */);
    ApplicationTask task = context.getInstance(ApplicationTask.class);
    task.run();
}

The “some configuration mechanism here” section varies by framework. In Guice it’s a programmatically setup “module” which determines how things are connected to each other, and in Spring it’s a declarative mix of XML and Annotations. The setup method does a load of processing, perhaps some reflection and classloading, and maybe even some obscure proxying, but essentially just calls a lot of constructors and links everything together. The exact execution of this is a bit of a mystery black box, but in the end if you’re lucky, you can just get an instance of your application entry point and everything will be good to go.

What’s the problem?

How many interdependent components does your application have that need to keep references to each other? How many different real-world configurations will you actually need to support. Does this justify having a whole extra sizable chunk of bloat just to create components and connect them to each other. How bad is it really to do this?:

public static void main(String[] args) {
    ServiceClient client = new HttpServiceClient(/* some parsed command line args */);
    ApplicationTask task = new ApplicationTask(client);
    task.run();
}

No frameworks, no annotations, a clear flow of logic which makes sense under debug, exceptions can be caught and handled gracefully, and the compiler will complain if you haven’t supplied the right arguments to a constructor. It’s simple and clear, and doesn’t increase your bytecode volume by several megabytes.

Unless your application is very large, this creates a setup which is less complex, easier to debug, and provides the same levels of testability as using a DI framework. You also don’t have to deal with embedded DSL or XML configuration, weird generated proxy classes, or being bound into a strange cult-like ecosystem (that’s Spring again).

Yes, there are uses for this kind of tool, but unless your component graph is bigger than 10-20 pieces, it’s simply not worth it. Just specify your dependencies explicitly and get on with your life.