Dependency Injection In Spring :
Dependency injection is a jargon created by Martin Fowler and it is also called as inversion of control. In object oriented design, objects have relationship with one another. A class (A) can have attributes (B) and methods. Those attributes are again instances of another class (C). If class (A) wants to work and perform its objective, attributes (B) should be instantiated.
There are different ways to instantiate an object and we have seen a lot in our design pattern tutorial series. A simple and direct way is to use the “new” operator and call the constructor of Class (C) where we need that instance in class (A). This is class A has absolute control over creation of attribute (B). It decides which class (C) to call and how to call etc.

Now, if we outsource that ‘instantiation and supplying an instance’ job to some third party. Class (A) needs instance of class (C) to operate, but it outsources that responsibility to some third party. The designated third party, decides the moment of creation and the type to use to create the instance. The dependency between class (A) and class (C) is injected by a third party. Whole of this agreement involves some configuration information too. This whole process is called dependency injection.
Class :
private C Obj;
some Method(){
Obj = new C();
}
//With out DI (Dependency Injection)
Differentiating between Dependency Injection And Factory Pattern :
Factory design pattern and dependency injection may look related but we look at them with microscope then we can understand the are different. Even if we use a factory the dependent class has the responsibility of creating the instance but the core of dependency injection is separating that responsibility to external component.
Factory example :
Class A { private C obj; public void someMethod() { ... this.obj = MyObjectFactory.getC(); ... } }
With Dependency Injection :

Class A { private C obj; public void someMethod(C obj) { ... this.obj = obj; ... } }
With DI the contract is different, pass C’s instance to get the job done. So the responsibility is with an external person to decide.
Advantages of Dependency Injection :
- Loosely couple architecture.
- Separation of responsibility
- Configuration and code is separate.
- Using configuration, a different implementation can be supplied without changing the dependent code.
- Testing can be performed using mock objects.
Types of Dependency Injections :
Dependency injection is classified into three categories namely,
- Constructor Injection
- Setter Injection
- Interface-based Injection
Definition for the above are explicit. When the dependency is solved using constructor it is called constructor injection :-) That is, the dependent object is passed as a parameter in the dependent class’s constructor. Similarly for setter injection, the instance is injected using a setter method. In interface-based dependency injection, we will have an interface and on implementing it we will get the instance injected.
Spring DI :
Spring framework provides many modules and its core has an inversion of control (IOC) container. Spring’s IOC container is light-weight and it manages the dependency between objects using configurations. It wires the related objects together, instantiates and supplies them based on configuration. In Spring, these objects are called managed objects. Spring and dependency injection is a large area and requires multiple articles to get an indepth idea. In this tutorial, my intent is to give an introduction and subsequently write more articles on it.
Two most popular ways in Spring for DI is, constructor and setter injection. Configuration for dependency are done using Spring-configuration XML or using annotations. Annotations are mostly preferred for their ease of use. Spring manages these objects using BeanFactory. When an instance is created, by default they are singletons and this can be changed using the configuration.
Circular Dependency :
What is circular dependency and tell about it is a popular question in Spring interviews. A -> B -> A, A is dependent on B and vice-versa. Spring’s IOC container will detect such circular dependencies at runtime and throwsObjectCurrentlyInCreationException. This is more prevalent in the case of constructor injection.
Spring Dependency Injection Using Annotations :
WildAnimal.java – Interface backbone using which dependency injection is done.
package com.mycompany.spring.ioc; public interface WildAnimal { public String sound() ; }
Lion.java – Implements the above interface and becomes a possible candidate for injection.
package com.mycompany.spring.ioc; public class Lion implements WildAnimal { public String sound() { return "Roar"; } }Wolf.java – another implementation of interface. This is the selected implementation for injection. @Service tells the spring IOC container to use this class.
package com.mycompany.spring.ioc;import org.springframework.stereotype.Service; @Service public class Wolf implements WildAnimal { public String sound() { return "Howl"; } }
Zoo.java – Zoo depends on WildAnimal and uses setter injection. @Autowired tells the Spring IOC container to find configured object of this type and inject an instance at runtime.
package com.mycompany.spring.ioc; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class Zoo { private WildAnimal wild; @Autowired public void setWild(WildAnimal wild) { this.wild = wild; } public void testSound() { System.out.println(wild.sound()); } }
spring-context.xml – gives the configuration information to the spring container. In this I describe that we are using annotation based configurations.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- Dependency Injection with annotations --> <context:component-scan base-package="com.mycompany.spring.ioc" /> <mvc:annotation-driven /> <!-- Dependency Injection without annotations --> <!-- <bean id="wild" class="com.javapapers.spring.ioc.Wolf" /> <bean id="zoo" class="com.javapapers.spring.ioc.Zoo"> <property name="wild" ref="wild" /> </bean> --> </beans>TestDI.java – loads the spring configuration and gets the bean. Spring IOC container based on annotations, provides the Wolf.java instance at runtime.
package com.mycompany.spring.ioc;import org.springframework.beans.factory.BeanFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDI { public static void main(String[] args) { ApplicationContext appContext = new ClassPathXmlApplicationContext("META-INF/spring-context.xml"); BeanFactory factory = appContext; Zoo zoo = (Zoo) factory.getBean("zoo"); zoo.testSound(); } }Spring Dependency example using XML
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- Dependency Injection with annotations --> <!-- <context:component-scan base-package="com.mycompany.spring.ioc" /> <mvc:annotation-driven /> --> <!-- Dependency Injection without annotations --> <bean id="wild" class="com.javapapers.spring.ioc.Wolf" /> <bean id="zoo" class="com.javapapers.spring.ioc.Zoo"> <property name="wild" ref="wild" /> </bean> </beans>
What is Inversion of Control?
Inversion of Control is a principle in software engineering by which the control of objects or portions of a program is transferred to a container or framework. It is most often used in the context of object-oriented programming.By contrast with traditional programming, in which our custom code makes calls to a library, IoC enables a framework to take control of the flow of a program and make calls to our custom code. In order to make this possible, frameworks are defined through abstractions with additional behavior built in. If we want to add our own behavior, we need to extend the classes of the framework or plugin our own classes.The advantages of this architecture are:
- decoupling the execution of a task from its implementation
- making it easier to switch between different implementations
- greater modularity of a program
- greater ease in testing a program by isolating a component or mocking its dependencies and allowing components to communicate through contracts
Inversion of Control can be achieved through various mechanisms such as: Strategy design pattern, Service Locator pattern, Factory pattern, and Dependency Injection (DI).
We’re going to look at DI next.
3. What is Dependency Injection?
Dependency injection is a pattern through which to implement IoC, where the control being inverted is the setting of object’s dependencies.
The act of connecting objects with other objects, or “injecting” objects into other objects, is done by an assembler rather than by the objects themselves.
Here’s how you would create an object dependency in traditional programming:
1
2
3
4
5
6
7
| public class Store { private Item item; public Store() { item = new ItemImpl1(); } } |
In the example above, you can see that in order to instantiate the item dependency of a Store object you have to specify which implementation of interface Item we will use within the Store class itself.
By using DI, we can rewrite the example without specifying the implementation of Item that we want:
1
2
3
4
5
6
| public class Store { private Item item; public Store(Item item) { this .item = item; } } |
The implementation of Item to be injected will then be provided through metadata, as we will see in the examples below.
Both IoC and DI are simple concepts, but have deep implications in the way we structure our systems, so they’re well worth understanding well.
4. The Spring IoC Container
An IoC container is a common characteristic of frameworks that implement IoC.
In the Spring framework, the IoC container is represented by the interface ApplicationContext. The Spring container is responsible for instantiating, configuring and assembling objects known as beans, as well as managing their lifecycle.
The Spring framework provides several implementations of the ApplicationContext interface — ClassPathXmlApplicationContext and FileSystemXmlApplicationContext for standalone applications, and WebApplicationContext for web applications.
In order to assemble beans, the container uses configuration metadata, which can be in the form of XML configuration or annotations.
Here is one way to manually instantiate a container:
1
2
| ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml" ); |
5. Dependency Injection in Spring
In order to set the item attribute in the example above, we can use metadata that will be used for assembling objects at runtime by the Spring container.
Dependency Injection in Spring can be done through constructors or setters.
5.1. Constructor-Based Dependency Injection
In the case of constructor-based dependency injection, the container will invoke a constructor with arguments each representing a dependency we want to set.
Resolving each argument is done primarily by the type of the argument, followed by name of the attribute and index for disambiguation. The configuration of a bean and its dependencies can be done using annotations:
1
2
3
4
5
6
7
8
9
10
11
12
13
| @Configuration public class AppConfig { @Bean public Item item1() { return new ItemImpl1(); } @Bean public Store store() { return new Store(item1()); } } |
The @Configuration annotation indicates that the class is a source of bean definitions and can be used on multiple configuration classes. The @Bean annotation is used on a method to define a bean. If you do not specify a custom name, the method name will be used.
If using the default singleton scope for a bean, each time a method annotated with @Bean is called, Spring checks first if a cached instance of the bean already exists and only creates a new one if it doesn’t exist. If the prototype scope is specified, then a new bean instance is returned for each call of the method.
Another way to create the configuration of the beans is through XML configuration:
1
2
3
4
| < bean id = "item1" class = "org.baeldung.store.ItemImpl1" /> < bean id = "store" class = "org.baeldung.store.Store" > < constructor-arg type = "ItemImpl1" index = "0" name = "item" ref = "item1" /> </ bean > |
5.2. Setter-Based Dependency Injection
For setter-based DI, the container will call setter methods of your class, after invoking a no-argument constructor or no-argument static factory method to instantiate the bean. Let’s create this configuration using annotations:
1
2
3
4
5
6
| @Bean public Store store() { Store store = new Store(); store.setItem(item1()); return store; } |
We can also use XML for the same configuration of beans:
1
2
3
| < bean id = "store" class = "org.baeldung.store.Store" > < property name = "item" ref = "item1" /> </ bean > |
Constructor-based and setter-based types of injection can be combined for the same bean. It is recommended by the Spring documentation to use constructor-based injection for mandatory dependencies, and setter-based injection for optional ones.
5.3. Autowiring Dependencies
Wiring allows the Spring container to automatically resolve dependencies between collaborating beans by inspecting the beans that have been defined.
There are four modes of autowiring a bean using an XML configuration:
- no: the default value – this means no autowiring is used for the bean and the dependencies have to be explicitly named
- byName: autowiring is done based on the name of the property, therefore Spring will look for a bean with the same name as the property that needs to be set
- byType: similar to the byName autowiring, only based on the type of the property, which means Spring will look for a bean with the same type of the property to set; if more than one bean of that type is found, the framework throws an exception
- constructor: autowiring is done based on constructor arguments, meaning Spring will look for beans with the same type as the constructor arguments
For example, let’s autowire the item1 bean defined above by type into the store bean:
1
2
3
4
5
6
7
8
9
| @Bean (autowire = Autowire.BY_TYPE) public class Store { private Item item; public setItem(Item item){ this .item = item; } } |
You can also inject beans using the @Autowired annotation for autowiring by type:
1
2
3
4
5
| public class Store { @Autowired private Item item; } |
If there is more than one bean of the same type, you can add the @Qualifier annotation to reference a bean by name:
1
2
3
4
5
6
| public class Store { @Autowired @Qualifier ( "item1" ) private Item item; } |
Let’s autowire beans by type through XML configuration:
1
| < bean id = "store" class = "org.baeldung.store.Store" autowire = "byType" > </ bean > |
Now let’s inject a bean named item into the item property of store bean by name through XML:
1
2
3
4
| < bean id = "item" class = "org.baeldung.store.ItemImpl1" /> < bean id = "store" class = "org.baeldung.store.Store" autowire = "byName" > </ bean > |
You can also override the autowiring by defining dependencies explicitly through constructor arguments or setters.
5.4. Lazy Initialized Beans
By default, the container creates and configures all singleton beans during initialization. To avoid this, you can specify the lazy-init attribute with value true on the bean configuration:
1
| < bean id = "item1" class = "org.baeldung.store.ItemImpl1" lazy-init = "true" /> |
As a consequence, the item1 bean will be initialized only when it is first requested, and not at startup. The advantage of this is faster initialization time, but the trade-off is that configuration errors may be discovered only after the bean is requested, which could be several hours or even days after the application has already been running.
6. Conclusion
In this article, we have presented the concepts of inversion of control and dependency injection and exemplified them in the Spring framework.
You can read more about these concepts in Martin Fowler’s articles:
And you can learn more about the Spring implementations of IoC and DI in the Spring Framework Reference Documentation.
Thanks for sharing this informative content , Great work
ReplyDeleteLeanpitch provides online training in Agile coach during this lockdown period everyone can use it wisely.
Certified agile coaching Bangalore
Thanks for sharing this informative content , Great work
ReplyDeleteCreative Thinking for creating an impact!
Product Thinking Community introduces PT Labs powered by Leanpitch
Product thinking conference
Thanks for sharing this informative content , Great work
ReplyDeleteLeanpitch provides online training in Product Management Launchpad during this lockdown period everyone can use it wisely.
Product Management Workshop