Understanding Dependency Injection (DI)

Java objects work and communicate with each other to build a working application. But, to what extent the involved application classes have been independent of each other, to increase their re-usability, is the prime concern. Spring, as an open source framework, provides the efficiency to attain such re-usability and modularity through the concept of Dependency Injection(DI). Dependency injection glues the concerned application classes together at run-time, keeping them independent of each other at the same time.

Assume that, we have two classes as below:

See that, class B has tight coupling or too much dependency on class A, as it needs class A to create a new instance, so that B can call it’s sayHello method. So, if I have something like this in our application, how much modularity and re-usable capability have we achieved? The answer is ‘none’, since class B will always be dependent on A. Then there comes a very generous Spring and says to B, ‘Hey B! Let me inject the instance of A, whenever my container gets initialized. You no longer have to wait for A to give you an instance of itself. I will do it for you and inject A‘s instance directly into your class at runtime. You just need to configure me a little.’ Now, B is really thankful to Spring, so assuming that Spring configuration has been done (for Dependency Injection) , B modifies itself to reduce the dependency on A as:

And the XML configuration for the dependency injection has been done like:

This is known as Setter Based Dependency Injection.

Now, here is an important point to note, that if you declare another instance variable inside B, for some class C, we would expect a runtime exception for this, since the framework expects all of the properties of class B to be set in the application context for dependency injection. This constraint can however be removed if using Annotations.


Let’s further dig this, we can say that B passively depends on the Spring container for its dependency on A. The instance of A is injected into B usually when some other class or application component instantiates B. There is a special object that gets created to resolve configured dependencies, known as the Spring IoC container. The container actually inspects what all components it is asked to create during the runtime of the application. If class B needs to be instantiated, the container figures out all of it’s dependencies and starts creating them one by one, walking down the line, until all the dependencies have been resolved. These dependencies get injected then and there.

Now, does this dependency thing reduce coupling? Yes, to the extent, until we configure interfaces instead of classes with concrete method implementations. We will see the difference with Annotations below.

So, how does Annotations make it more simpler for us? 

To allow using Annotations in you application, you first need to define the following into you spring context XML:

Let us see first, how the above spring configuration and class B will change with annotations. Spring context XML would now contain something like:

And the class B will change to something like:

or,

or,

You might have noticed the difference all the three scenarios, the first class B has autowiring done on property (no setter method required), the second one has autowiring done on the setter method and the third one has autowiring done on the constructor method. All these scenario attempts autowiring by type, and autowires ‘a’ to the bean matching the same type in the spring context XML, assuming that there exists only one bean definition of this type (we will be contradicting this point later).

@Autowired tells the Spring IOC container to find configured bean of this type and inject an instance of it at runtime.

Next is that, how coupling can reduced by using autowiring with interfaces. If the dependency of some class D is on some particular interface, this D class doesn’t need to worry of the actual implementation of this interface, thus providing us to inject any desired implementation into class D at runtime. This is made possible if the component scan has been enabled in the application.

Let’s quickly see an example for this.

The spring context XML will be having something like:

Note that we have now added a component-scan in the application context XML, because of which we no more need to define the beans in the XML. The base-package value defined will now be automatically scanned for the component classes with the @Component annotation, whenever the Spring container initializes at server startup.

The respective classes would now look like:

In the above snippet at line number 27, IA b statement has @Autowired annotation, which will try autowiring the respective component By Type as we have already discussed, but to it’s astonishment, there exists two components of the same type (annotated as @Component(“b”) and @Component(“c”)). What the Spring container will do now, is, it will start trying to autowire the component by name instead of by type.

IA b will now match with the component annotated as @Component(“b”) and this component gets injected into class D at runtime. Similarly IA c will now match with the component annotated as @Component(“c”) and also gets injected into class D at runtime. So, I have contradicted my point that I mentioned earlier, that there can exists only one bean definition of a particular type. But the actual verdict is, that we can have multiple bean definitions of the same type, which when found while autowiring By Type, will fall back to match the configured bean definitions By Name.

Hope you might be clear on this more than ever before. For any queries, put it forth as comment to this article. Thanks to my friend Jimish Bhayani for reviewing and help bringing out the best.

Receive our updates to your inbox

Get more stuff like this
in your inbox

Subscribe to our mailing list and get interesting stuff and updates to your email inbox.