Dependency Injection is a pattern that is used to remove dependency from the programming code so that it becomes easy to manage and test the application.
Dependency Lookup (DL):
It is an approach where you get the resources after demand. There are various methods to get resources.
- To get the resource directly by calling a new keyword.
Example:
A obj = new AImpl();
- Factory Method: By calling a static factory method.
Example:
A obj = A.getA();
- Java Directory Naming Interface (JNDI):
Example:
Context ctx = new InitialContext();
Context environmentCtx = (Context) ctx.lookup(“java:comp/env”);
A obj = (A)environmentCtx.lookup(“A”);
Problems in Dependency Lookup:
There are two main problems in this approach:
- Tight coupling: If a resource is changed, a lot of modification is required in the programming code.
- Not easy for testing: It creates a lot of problems while testing mainly in black-box testing.
Dependency Injections makes the code loosely coupled and easy for testing. An example is given below:
class Employee{ Address address; Employee(Address address){ this.address=address; } public void setAddress(Address address){ this.address=address; } }
There are two ways to perform dependency injection:
- By using Constructor
- By using the Setter method
Dependency Injection using Constructor:
Here, the dependency can be injected using constructor and is done through the bean configuration file. The properties to be set are defined under <constructor-arg> tag in the bean configuration file.
Example:
Step 1: Book.java
public class Book { private int id; private String bookName; public Book() {System.out.println("Java");} public Book(int id) {this.id = id;} public Book(String bookName) { this.bookName = bookName;} public Book(int id, String bookName) { this.id = id; this.bookName = bookName; } void display(){ System.out.println(id+" "+bookName); } }
Step 2: applicationContext.java
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p" xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="book" class="com.spring.example.Book"> <constructor-arg value="1" type="int"></constructor-arg> </bean> </beans>
Step 3: Main.java
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.*; public class Main { public static void main(String[] args) { Resource r=new ClassPathResource("applicationContext.xml"); BeanFactory factory=new XmlBeanFactory(r); Book b=(Book)factory.getBean("book"); b.display(); } }
Dependency Injection Using Setter Method:
Here, the dependency can be injected using setter/getter methods and is done through the bean configuration file. The properties to be set are defined under the <property> tag in the bean configuration file.
Example:
Step 1: Book.java
public class Book { private int id; private String bookName; private String author; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } void display(){ System.out.println(id+" "+bookName+" "+author); } }
Step 2: applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:p="https://www.springframework.org/schema/p" xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="book" class="com.spring.example.Book"> <property name="id"> <value>1</value> </property> <property name="bookName"> <value>The Complete Reference J2EE</value> </property> <property name="author"> <value>Herbert Schildt</value> </property> </bean> </beans>
Step 3: Main.java
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.*; public class Main { public static void main(String[] args) { Resource r=new ClassPathResource("applicationContext.xml"); BeanFactory factory=new XmlBeanFactory(r); Book b=(Book)factory.getBean("book"); b.display(); } }
Difference between Setter Dependency Injection and Constructor Dependency Injection:
Setter Dependency Injection (SDI) | Constructor Dependency Injection (CDI) |
Readability is poor, as there is a lot of code in the application. | Readability is good as dependency is separately present in the code. |
The bean should include setter and getter methods. | The bean should contain a matching constructor with argument; otherwise, BeanCreationException will be thrown. |
It is preferred when properties are less and contain mutable objects. | It is preferred when properties are more and contain immutable objects. |
There is a scope of circular dependency, and partial dependency is available. | There is no scope of circular dependency or partial dependency. |
It requires @Autowired annotation to increase the coupling between the classes and DI containers. | It does not require the addition of @Autowired annotation. |