In a well-designed Java application, the classes should be as independent as possible. Such a design promotes reusability of components. It also makes it easier to unit test the various components.
The concept of dependency injection promotes loose coupling among Java objects.
In this tutorial, we’ll talk about the dependency injection in Spring framework.
Inversion of Control is a software engineering principle which delegates the responsibility of controlling the application’s flow to a framework. To make it possible, the frameworks use abstractions and rely on object graphs generated at runtime.
There are several advantages of using the IoC principle:
We can achieve Inversion Of Control either by using a Strategy Design Pattern, Service locator Pattern or Dependency Injection.
Dependency Injection is one of the design patterns which allows us to achieve Inversion Of Control.
In a traditional programming style, we’ll have our classes written as:
public class Person { private Address address; public Person() { this.address = new Address(); } ... }
public class Person { private Address address; public Person(Address address) { this.address = address; } ... }
Spring provides an IoC container which is responsible for instantiating, configuring and managing the lifecycle of Spring beans. In Spring, any POJO is referred to as a Spring bean.
The Spring ApplicationContext interface represents its IoC container and we have several implementation classes available. Some of these include ClassPathXmlApplicationContext, FileSystemXmlApplicationContext, and WebApplicationContext.
Let’s instantiate the Spring container using ClassPathXmlApplicationContext:
ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Spring supports three types of dependency injection:
In a constructor-based injection, Spring will use the matching constructor to resolve and inject the dependency.
We can either configure the beans in applicationContext.xml:
<bean id="address" class="com.programmergirl.domain.Address"/> <bean id="person" class="com.programmergirl.domain.Person"> <constructor-arg ref="address"/> </bean>
<context:component-scan base-package="com.programmergirl.domain" />
package com.programmergirl.domain; @Component public class Person { private Address address; @Autowired public Person(Address address) { this.address = address; } } package com.programmergirl.domain; @Component public class Address { ... }
@Component public class Person { private Address address; @Autowired @Qualifier("address1") public void setAddress(Address address) { this.address = address; } }
Setter-based dependency injection is achieved through the setter method on the bean after instantiating it using a no-arg constructor or no-argument static factory.
We can configure it using XML as:
<bean id="address" class="com.programmergirl.domain.Address"/> <bean id="person" class="com.programmergirl.domain.Person"> <property name="address" ref="address"/> </bean>
@Component public class Person { private Address address; ... @Autowired public void setAddress(Address address) { this.address = address; } }
We can also inject dependencies using fields or properties of a class. To do so, we can simply use the @Autowired annotation over the field:
@Component public class Person { @Autowired private Address address; ... }
As per Spring documentation:
In this quick article, we discussed what is dependency injection. We also discussed the types of dependency injection in Spring framework.