Spring Dependency Injection
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.
Contents
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>
<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; } }
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; } }
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()); } }
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()); } }
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(); } }
--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; } }
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(); } }
Product product = (Product)ctx.getBean("product");
--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; } }
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); } }
@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 { }
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(); } }
Field Area:180