Spring Dependency Injection

By Arvind Rai, March 11, 2023
This page will walk through the Spring dependency injection through constructor and setter based injection and using @Autowire annotation. In dependency injection, we inject one or more beans to a single bean via constructor or setter method. Spring also provides autowired dependency injection in which we only need to annotate our field, setter method or constructor parameter by @Autowire annotation. Dependency injection can be resolved using XML or JavaConfig. Now we will discuss dependency injection in detail.

Gradle Dependencies

Find the gradle file to resolve the spring JAR dependencies.
dependencies {
    compile 'org.springframework.boot:spring-boot-starter:1.2.7.RELEASE'
}  

Spring Dependency Injection

In our daily programming life, we usually create java classes which use one or more than one objects to work. While creating such objects, we can pass other objects via constructor or using setter methods. While working with spring beans, to handle such classes, spring provides two types of dependency injection.

Constructor-based dependency Injection : A bean is instantiated with other beans via constructor.
Setter-based dependency Injection : A bean is first instantiated, and then other bean dependency is resolved by setter method.

Using constructor or setter-based dependency injection is matter of our choice. We can go ahead with any of these two dependency injection.

Constructor and Setter based Dependency Injection using XML Configuration

Find the spring application context XML file. Here we have created four beans.
spring-config.xml
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="mycompany" class="com.concretepage.bean.Company">
	   <property name="compId" value="100"/>
	   <property name="compName" value="ConcretePage"/>
	</bean>
	<bean id="myaddress" class="com.concretepage.bean.Address">
	    <constructor-arg index="0" value="200"/>
	    <constructor-arg index="1" value="Varanasi"/>
	</bean>
	<bean id="product" class="com.concretepage.bean.Product">
	   <property name="company" ref="mycompany"/>
	   <property name="address" ref="myaddress"/>
	</bean>
	<bean id="employee" class="com.concretepage.bean.Employee">
	   <constructor-arg index="0" ref="mycompany"/>
	   <constructor-arg index="1" ref="myaddress"/>		   
	</bean>				
</beans> 
Two beans mycompany and product has been created using spring setter based dependency injection and two beans myaddress and employee has been created using constructor based dependency injection. For setter based dependency injection, we need to use <property> tag and for constructor based dependency injection spring provides <constructor-arg> tag. To refer a bean for dependency injection, spring provides ref attributes. Find the meaning of spring bean tags being used.

<bean> : It defines a bean. We need to pass fully qualified class name.
<property> : Using this tag, we set the values in setter method of bean. Using this tag, we resolve setter based dependency injection.
<constructor-arg> : Using this tag, we pass the values to the bean constructor argument. index attribute defines the sequence of argument. Using this tag we resolve constructor based dependency injection.

Now find the classes which are being used for dependency injection.
Address.java
package com.concretepage.bean;
public class Address {
	private int addId;	
	private String city;
	public Address(int addId, String city) {
		this.addId = addId;
		this.city = city;
	}
	public int getAddId() {
		return addId;
	}
	public String getCity() {
		return city;
	}
} 
The above class has constructor and getter method. This class will be used for constructor based dependency injection.
Company.java
package com.concretepage.bean;
public class Company {
	private int compId;	
	private String compName;
	public int getCompId() {
		return compId;
	}
	public void setCompId(int compId) {
		this.compId = compId;
	}
	public String getCompName() {
		return compName;
	}
	public void setCompName(String compName) {
		this.compName = compName;
	}
} 
The above class will be used for setter based dependency injection.
Employee.java
package com.concretepage.bean;
public class Employee {
	private Company company;
	private Address address;
	public Employee(Company company, Address address) {
		this.company = company;
		this.address = address;
	}
	public void print() {
		System.out.println("CompId:"+company.getCompId()+", Company name:"+ company.getCompName());
		System.out.println("AddId:"+address.getAddId()+", City:"+ address.getCity());
	}
} 
The Employee class will be used for constructor based dependency injection.
Product.java
package com.concretepage.bean;
public class Product {
	private Company company;
	private Address address;
	public Company getCompany() {
		return company;
	}
	public void setCompany(Company company) {
		this.company = company;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}
	public void print() {
		System.out.println("CompId:"+company.getCompId()+", Company name:"+ company.getCompName());
		System.out.println("AddId:"+address.getAddId()+", City:"+ address.getCity());
	}	
} 
The Product class will be used for setter based dependency injection. Now we will test the application using the class as follows.
SpringDemo.java
package com.concretepage;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.concretepage.bean.Employee;
import com.concretepage.bean.Product;
public class SpringDemo {
    public static void main(String... args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
            System.out.println("--Result by Setter based Dependency Injection--");
            Product product = (Product)context.getBean("product");
            product.print();
            System.out.println("--Result by Constructor based Dependency Injection--");
            Employee employee = (Employee)context.getBean("employee");
            employee.print();
    } 
} 
Find the output
--Result by Setter based Dependency Injection--
CompId:100, Company name:ConcretePage
AddId:200, City:Varanasi
--Result by Constructor based Dependency Injection--
CompId:100, Company name:ConcretePage
AddId:200, City:Varanasi 

Constructor and Setter based Dependency Injection using JavaConfig

In JavaConfig, the class is annotated with @Configuration annotation. We define our bean using spring @Bean annotation. Here constructor and setter based dependency injection is simply creating java class using constructor or setter method. Find the configuration class.
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.concretepage.bean.Address;
import com.concretepage.bean.Company;
import com.concretepage.bean.Employee;
import com.concretepage.bean.Product;
@Configuration
public class AppConfig {
	@Bean(name="mycompany")
	public Company getCompany() {
		Company comp = new Company();
		comp.setCompId(100);
		comp.setCompName("ConcretePage");
		return comp;
	}
	@Bean(name="myaddress")
	public Address getAddress() {
		Address add = new Address(200, "Varanasi");
		return add;
	}
	@Bean(name="product")	
	public Product getProduct() {
		Product product = new Product();
		product.setAddress(getAddress());
		product.setCompany(getCompany());
		return product;
	}
	@Bean(name="employee")	
	public Employee getEmployee() {
		Employee employee = new Employee(getCompany(),getAddress());
		return employee;
	}
} 
To test the application, I am using the Main class as follows.
SpringDemo.java
package com.concretepage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.concretepage.bean.Employee;
import com.concretepage.bean.Product;
public class SpringDemo {
   public static void main(String[] args) {
       AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
       ctx.register(AppConfig.class);
       ctx.refresh();
       System.out.println("--Result by Setter based Dependency Injection--");
       Product product = (Product)ctx.getBean("product");
       product.print();
       System.out.println("--Result by Constructor based Dependency Injection--");
       Employee employee = ctx.getBean(Employee.class);
       employee.print();
       ctx.close();
   }
}  
We can call bean by passing class name or by using bean name. Find the code snippet to use bean name.
Product product = (Product)ctx.getBean("product");
 
Find the output.
--Result by Setter based Dependency Injection--
CompId:100, Company name:ConcretePage
AddId:200, City:Varanasi
--Result by Constructor based Dependency Injection--
CompId:100, Company name:ConcretePage
AddId:200, City:Varanasi 

Spring Dependency Injection with @Autowire Annotation

Spring provides @Autowire annotation that can make field, constructor or setter method autowired using spring dependency injection. In our example we will autowire a field. We can create bean using annotations from the package org.springframework.stereotype.

@Component : It indicates that the class is a component and eligible to be autowired.
@Service : It indicates that a class is service and eligible to be autowired.
@Repository: It indicates that the class will act as repository and eligible to be autowired.

For the example we have two classes CalcUtil annotated with @Component and FarmerService annotated with @Service. CalcUtil will be autowired using @Autowire annotation in FarmerService class at field level. Find the CalcUtil class.
CalcUtil.java
package com.concretepage.bean;
import org.springframework.stereotype.Component;
@Component
public class CalcUtil {
	public int multiply(int num1, int num2) {
		return num1 * num2;
	}
} 
Now find the FarmerService class.
FarmerService.java
package com.concretepage.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class FarmerService {
   @Autowired	
   private CalcUtil calcUtil;
   public int getFieldArea() {
	   return calcUtil.multiply(12, 15);
   }
} 
In java configuration class, we need to use @ComponentScan(basePackages="com.concretepage.bean"), to scan our beans. Find the JavaConfig file.
AppConfig.java
package com.concretepage;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages="com.concretepage.bean")
public class AppConfig {
} 
Run the application using the class as follows.
SpringDemo.java
package com.concretepage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.concretepage.bean.FarmerService;
public class SpringDemo {
   public static void main(String[] args) {
       AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
       ctx.register(AppConfig.class);
       ctx.refresh();
       FarmerService farmer = ctx.getBean(FarmerService.class);
       System.out.println("Field Area:"+ farmer.getFieldArea());
       ctx.close();
   }
}  
Find the output.
Field Area:180
 

Download Complete Source Code

POSTED BY
ARVIND RAI
ARVIND RAI







©2024 concretepage.com | Privacy Policy | Contact Us