Spring Dependency Injection
Introduction:
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(IoC):
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:
- decouples the task implementation from its execution
- modules are pluggable and can be easily replaced with their equivalent
- eases out the modular testing
We can achieve Inversion Of Control either by using a Strategy Design Pattern, Service locator Pattern or Dependency Injection.
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(); } ... }
When using dependency injection, we’ll not create objects on our own and rather inject them. Our Person class would then look something like:
public class Person { private Address address; public Person(Address address) { this.address = address; } ... }
Dependency Injection In Spring:
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");
Here, the applicationContext.xml is the file that holds the metadata required to assemble beans at runtime.
Spring supports three types of dependency injection:
1. Constructor-Based 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>
Or, we can enable the <component-scan/> in our applicationContext.xml:
<context:component-scan base-package="com.programmergirl.domain" />
On enabling component scan, we can make the Spring configurations using the annotations. Our classes would then look like:
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 { ... }
Spring, by default, wires the beans by their type. If there are more than one beans of the same type, we can use @Qualifier annotation to reference a bean by its name:
@Component public class Person { private Address address; @Autowired @Qualifier("address1") public void setAddress(Address address) { this.address = address; } }
Assuming we have two Address beans – address1 and address2, our address1 bean will be injected into Person class while dependency resolution.
2. Setter Injection:
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>
On the other hand, when using annotations, we’ll have:
@Component public class Person { private Address address; ... @Autowired public void setAddress(Address address) { this.address = address; } }
3. Property-Based Injection:
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; ... }
considering we’re using annotation based configurations.
Noteworthy Points:
As per Spring documentation:
- We should use constructor injection for mandatory dependencies
- Setter-based injections should be used for dependencies that are optional in nature
- Spring uses reflection for injecting the field-injected dependencies. So, field-based injection is a costlier approach and we should avoid using it
Conclusion:
In this quick article, we discussed what is dependency injection. We also discussed the types of dependency injection in Spring framework.
Published on Java Code Geeks with permission by Shubhra Srivastava, partner at our JCG program. See the original article here: Spring Dependency Injection Opinions expressed by Java Code Geeks contributors are their own. |