I have had the pleasure of interviewing a large number of java  developers in 2014, from fresh grads to seasoned veterans. One of the overriding surprises for me has been the lack of understanding regarding dependency injection, inversion of control and Spring (specifically Spring core).

As a quick refresher, let’s discuss dependency injection (DI).  Objects have dependencies on other objects to do whatever it is that it needs to do. A car has a dependency on an engine to be able to move. It has a dependency on a radio in order for the driver to be entertained. Programmatically, you can have the car create it’s dependencies like so:

public class Car {

 
private final Engine engine;

private final Radio radio;

public Car(){

engine = new Engine();

radio = new Radio();

}

}

There are a number of problems with this approach, the main issue is that it’s really hard to test. You can’t test the functionality of the car without creating a radio, and creating a radio, and creating all the other things.  If the thing you’re testing on has lots of expensive dependencies such as databases then it’s going to be exceptionally slow.  It may not even be possible to create your dependencies during a test, making it impossible to try out. If your object relies on a fully functioning database cluster, chances are you aren’t able to just start one up for the purpose of testing.

This is where dependency injection comes in.  Simply put, the things your object needs (i.e. what it depends on) get given to it (injected). The object plays no role in creation, and just aggregates objects together for some purpose. It can exclusively focus on the functionality or activity that it is designed to perform.


public class Car {
 

private final Engine engine;

private final Radio radio;
 

public Car(Engine engine, Radio radio){

this.engine = engine;

this.radio = radio;

}

}

Now you can pass in whatever engine or radio you want.  This means that it can be mocked out for tests; you can assert on the interaction between the object and it’s dependencies which will result in much cleaner seperation of concerns. It also allows you to swap the implementation- it can be a V8 for a super car. It can be a hybrid for an eco car.  The important thing is a car doesn’t care, or more importantly, it shouldn’t care. Its job is to use the engine to get power for the radio, and wheels, and windscreen wipers. . 

So far we have not touched Spring. There is never a need to touch Spring with regards to DI.  Spring is one of many possible ways of injecting dependencies.  There are other frameworks too, like Google Guice. But if you only take one thing away from reading this article then I hope it is the realisation that Dependency Injection is a style of programming and in no way requires a framework.

With Spring you create XML documents that outline how you would like the object to be created.  At runtime the Spring container then creates everything that is required in the application using reflection and injects the dependencies in.  It is one way of structuring an application, and it’s gotten very popular which is why people seem to find Spring and DI synonymous.

But, would it blow your mind to know that this is also dependency injection?

public class CarManufacturer {

public void buildACar(){

new Car(new PetrolEngine(), new RetroRadio());

}

}

It really is that simple. To quote Martin Fowler, “Dependency Injection is a 25-dollar term for a 5-cent concept”.  We’ve all spent years living in an XML hell and assuming this was the only way of doing things. It is a fallacy to believe that large scale systems cannot be built without a formal DI framework.  I’ve worked on 50,000 line codebases in which the only DI framework was the “new” keyword. It’s mighty powerful and is integrated into the language, and I can guarantee it has full IDE support.

These codebases are a joy to work on.  Application startup times can be sub-second for the entire thing. Testing is easy and clear; how many Spring projects actually test the wiring of the application?  The best feature by far is compile time safety.  With Spring we have taken one of Java’s greatest features, the fact you can compile and be sure your application is syntactically correct, and completely removed it. 

This is not meant as a Spring rant.  This is meant for the developer who has used Spring for five years and didn’t think there was another way.  Dependency injection and Spring are orthogonal concerns and should be treated as so.  We can all agree that dependency injection results in loosely coupled applications that can be well tested.  However,  next time you come to build your application, why not try to structure the dependency injection without a framework for a much leaner and understandable code base?

Image by Clare Bell

 

You Don’t Need Spring to Do Dependency Injection

Profile photo of Sam Atkinson
About The Author
- Sam Atkinson is the founder of corejavainterviewquestions.com. He has been a developer in the finance sector for seven years and is incredibly passionate about TDD.

7 Comments

  • cclaudiu
    Reply

    I agree with you in the beginning of the post, however i have to comment on these topics:
    “Dependency Injection is a style of programming and in no way requires a framework.”
    I see DI, indeed as a style of programming, but the real power of the DI(which is the specific implementation of IoC) relies on the injection container, which hence decouples the application logic from the injected dependencies.
    If you think DI is only passing responsibilities of injecting concrete instances to the callers of these objects, then you will end up “carrying” the dependencies to objects which are, and maybe should not be aware of how an object is instantiated.
    Carrying dependencies is often a code smell, since you cannot raise the dependency responsibility to the callee of callers…

    “DI framework was the “new” keyword. ”
    Well i don’t see this as DI. This is the before mentioned dependency carry-on process. Since DI should abstract, or take away the creation process of an object, into a separate module.

    ” how many Spring projects actually test the wiring of the application? ”
    Working heavily with Spring, i try as much as i can to use the programatically way of managing my dependencies through the use of annotations. Now we all know, that one can “validate” the correcteness of the wiring process when the application starts up, or in other terms, is being deployed. This might be cost some time depending upon the sizes of the application. But in many cases, you get the IDE support, when working with beans or DI.

    Thanks for the post!

  • Matt Melton
    Reply Report user

    DI is a form of Inversion of Control. I don’t think you should talk about DI without mentioning the composition root and object lifetimes.

    DI shouldn’t be confused with techniques that decouple code, such as composition. DI requires composition, but composition isn’t DI.

    Ctor construction doesn’t inject anything, it’s just a method of composing code to make it more manageable/readable. Unfortunately, this kind of construction is so coarse it’s not particularly useful in many real-world scenarios, like the web, where resources come and go.

  • None
    Reply

    Your EngineManufacturer.buildACar() should probably return the car…
    I think you are missing the point of Spring and Guice etc.
    Yes you are now injecting your dependencies for Car, but the problem that DI frameworks solve is large chains of objects. Your PetrolEngine and RetroRadio will themselves have dependencies. So now buildACar is embedding further static calls to your other manufacturer objects all the way down, which gets incredibly verbose and messy.
    On top of that you now have the famous testing problem, where you want the static manufacturer to return a mock car just so you can make sure that some particular method has been called on the mock car in some part of your test. The infamous solution is of course to have a static field in the manufacturer which you can set to a mock in your test, where you return that if it has been set. Then you have to remember to unset it again after each test, and make sure it’s threadlocal or tests with different mocks can’t run in parallel without causing each other to fail as they trample over each others mocks, and you need to do this for all your manufacturers in order to be able to test them properly. Yep, the “simple” solution, ends up being a real mess and a real drag on development.
    Much better to have a framework handling the dependency injection for you.

  • Mark
    Reply

    another point missed about Spring and Guice is that they do more than just DI/IoC – They do things like AOP.

    I’ve written plenty of “good” code without a framework – years before Spring showed up Yes, there are some pros to that. But they were NOT a joy to work on nor maintain. With Spring i was able to toss a bunch of my code. I didn’t have to maintain my own “informal” framework anymore nor all the other issues that it solved ( like remoting).

    I suggest taking a quick tour of Spring Boot. Whatever might suck about using a DI/IoC framework sort of disappears with all the goodies.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>