Learnitweb

Overview of dependency injection in Spring

Overview

In this tutorial, we’ll take a look at the concept of Dependency Injection and IoC (Inversion of Control). We’ll see types of Dependency Injection in Spring and how it is implemented in Spring. We’ll have separate tutorials for each type of Dependency Injection. In this tutorial, we’ll look at all these topics briefly.

Inversion of Control

Inversion of Control is a principle in software engineering which means that the control of creating and managing objects is passed to the external entity which can be a program, framework and in case of Spring called a container.

In Java, we create an object like the following:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Car {
private Engine engine;
public create(){
this.engine = new Engine();
}
// rest of the code for the class Test
}
class Car { private Engine engine; public create(){ this.engine = new Engine(); } // rest of the code for the class Test }
class Car {
	private Engine engine;
	
	public create(){
		this.engine = new Engine();
	}
	// rest of the code for the class Test
}

Here, the responsibility of creating the object is with the class Car. With Inversion of Control, this responsibility of creating objects is passed to the container. The container will create objects with all the dependencies required by the object.

Advantages of Inversion of Control

  • Increases decoupling. Decoupled code is much easier to manage.
  • Increased modularity
  • Because of increased decoupling, it is easier to switch between implementations.
  • Testing components is easy as components can be tested in isolation.

Dependency Injection

Whenever we create an application, it is made of many objects. Objects are dependent on each other to deliver the functionality desired from the application. Dependency Injection is just the other side of Inversion of Control. Dependency Injection means the dependencies are injected by the container and the object itself does not create the dependencies.

With dependency injection, the code of Car object will change like the following:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
class Car {
private Engine engine;
public create(Engine engine){
this.engine = engine;
}
// rest of the code for the class Test
}
class Car { private Engine engine; public create(Engine engine){ this.engine = engine; } // rest of the code for the class Test }
class Car {
	private Engine engine;
	
	public create(Engine engine){
		this.engine = engine;
	}
	// rest of the code for the class Test
}

This code does not have metadata which will define how the object should be configured. We’ll discuss about this in following sections.

Spring IoC Container

Spring IoC container is responsible for instantiating, configuring and assembling the beans. It is the Spring IoC container which does the core of the job. Spring IoC container is responsible of implementing Dependency Injection and Inversion of Control (IoC).

Spring IoC Container is responsible for managing beans. Spring IoC container is represented by org.springframework.context.ApplicationContext interface. ApplicationContext is a sub-interface of BeanFactory interface.

Following are few implementing classes of ApplicationContext:

  • AbstractApplicationContext
  • FileSystemXmlApplicationContext
  • ClassPathXmlApplicationContext
  • XmlWebApplicationContext

IoC container reads the metadata to configure the beans with all the dependencies. Metadata is commonly defined as an XML file or annotations.

There are two main types of dependency injection:

  • Constructor-based dependency injection
  • Setter-based dependency injection

Constructor-based Dependency Injection

In constructor-based dependency injection, container invokes a constructor with a number of arguments, where each argument represents a dependency.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class Car {
Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
}
public class Car { Engine engine; public Car(Engine engine) { this.engine = engine; } }
public class Car {
  Engine engine; 
  
    public Car(Engine engine) {
        this.engine = engine;
    }
}
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class Engine {
String manufacturer;
String type;
int cylinders;
public Engine(String manufacturer, String type, int cylinders) {
super();
this.manufacturer = manufacturer;
this.type = type;
this.cylinders = cylinders;
}
}
public class Engine { String manufacturer; String type; int cylinders; public Engine(String manufacturer, String type, int cylinders) { super(); this.manufacturer = manufacturer; this.type = type; this.cylinders = cylinders; } }
public class Engine {
  String manufacturer;
  String type;
  int cylinders;
  
  public Engine(String manufacturer, String type, int cylinders) {
    super();
    this.manufacturer = manufacturer;
    this.type = type;
    this.cylinders = cylinders;
  }
}
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<bean id="audi" class="com.learnitweb.components.Car">
<constructor-arg index="0" ref="engine" />
</bean>
<bean id="engine" class="com.learnitweb.dependency.Engine">
<constructor-arg index="0" value="audi" />
<constructor-arg index="1" value="automatic" />
<constructor-arg index="2" value="4" />
</bean>
<bean id="audi" class="com.learnitweb.components.Car"> <constructor-arg index="0" ref="engine" /> </bean> <bean id="engine" class="com.learnitweb.dependency.Engine"> <constructor-arg index="0" value="audi" /> <constructor-arg index="1" value="automatic" /> <constructor-arg index="2" value="4" /> </bean>
<bean id="audi" class="com.learnitweb.components.Car">
    <constructor-arg index="0" ref="engine" />
</bean>
<bean id="engine" class="com.learnitweb.dependency.Engine">
  <constructor-arg index="0" value="audi" />
  <constructor-arg index="1" value="automatic" />
  <constructor-arg index="2" value="4" />
</bean>

constructor-arg is used to provide the constructor based dependencies. Constructor Based Dependency Injection in Spring article discusses this type of dependency injection in more detail.

Setter Based Dependency Injection in Spring

Setter-based dependency is accomplished by the container calling setter methods on beans after invoking a no-argument constructor or a no-argument static factory method to instantiate your bean.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Component
public class Car {
//car has dependency on Engine
Engine engine;
@Autowired
public void setEngine(Engine engine) {
this.engine = engine;
}
public Engine getEngine() {
return engine;
}
}
@Component public class Car { //car has dependency on Engine Engine engine; @Autowired public void setEngine(Engine engine) { this.engine = engine; } public Engine getEngine() { return engine; } }
@Component
public class Car {
  //car has dependency on Engine
  Engine engine; 
  
  @Autowired
  public void setEngine(Engine engine) {
    this.engine = engine;
  }
  
  public Engine getEngine() {
    return engine;
  }
}

We can configure the same in XML using ref.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<bean id="audi" class="com.learnitweb.components.Car">
<property name="engine" ref="engine"></property>
</bean>
<bean id="audi" class="com.learnitweb.components.Car"> <property name="engine" ref="engine"></property> </bean>
<bean id="audi" class="com.learnitweb.components.Car">
  <property name="engine" ref="engine"></property>
</bean>

Autowiring beans

Spring provides us the feature of autowiring beans. It is not always mandatory to do explicit wiring. It means Spring can resolve dependencies automatically by looking beans in ApplicationContext.

There are following autowiring modes:

  • no: This is default mode. It means no autowiring.
  • byName: Autowiring by property name. In this mode, Spring looks for a bean with the same name as the property that needs to be autowired.
  • byType: Spring autowires the property if exactly one bean of the property type exists in the container.
  • constructor: It is similar to byType but this type of autowiring is done to constructor arguments.

Conclusion

In this tutorial, we discussed dependency injection in brief. It is important to learn these concepts are this is the base of Spring and which makes Spring popular.