Dependency Injection in Java Explained with Examples | Beginner to Advanced Guide

Reading Time: 14–17 minutes

Dependency Injection (DI) is a design principle and design pattern used to achieve loose coupling between classes. Instead of a class creating its own dependencies, the required dependencies are provided from outside.

Dependency Injection is widely used in modern Java applications, especially in frameworks like Spring Boot. It improves testability, flexibility, and maintainability of code.

This tutorial explains Dependency Injection from beginner to advanced level with simple examples, step-by-step implementation, and real-world understanding.

What is Dependency Injection

Dependency Injection is a technique where an object receives its dependencies from an external source instead of creating them internally.

Simple definition:

Do not create dependencies inside a class. Inject them from outside.

Understanding Dependency and Injection

What is Dependency

A dependency is an object that another object requires to perform its task.

Example: Car depends on Engine.

What is Injection

Injection means providing the required dependency from outside the class.

Why Do We Need Dependency Injection

Let us understand the problem first.

Problem Without Dependency Injection

Suppose a service directly creates its dependency.


package com.codekatha;

class MySQLDatabase {

    public void connect() {
        System.out.println("Connected to MySQL database");
    }
}

class UserService {

    private MySQLDatabase database = new MySQLDatabase();

    public void saveUser() {
        database.connect();
        System.out.println("User saved");
    }
}

Problems in This Approach

Tight coupling between classes
Difficult to switch database implementation
Hard to test
Violates Dependency Inversion Principle

If we want PostgreSQL instead of MySQL, we must modify UserService.

Solution – Dependency Injection

Instead of creating the dependency inside the class, we pass it from outside.

This reduces coupling and increases flexibility.

Key Idea Behind Dependency Injection

Remove object creation responsibility
Provide dependencies externally
Promote loose coupling
Improve testability

Implementing Dependency Injection Step-by-Step

Step 1 – Create Interface for Dependency


package com.codekatha;

interface Database {
    void connect();
}

Step 2 – Create Concrete Implementations


package com.codekatha;

class MySQLDatabase implements Database {

    public void connect() {
        System.out.println("Connected to MySQL database");
    }
}

class PostgreSQLDatabase implements Database {

    public void connect() {
        System.out.println("Connected to PostgreSQL database");
    }
}

Step 3 – Inject Dependency into Class


package com.codekatha;

class UserService {

    private Database database;

    public UserService(Database database) {
        this.database = database;
    }

    public void saveUser() {
        database.connect();
        System.out.println("User saved");
    }
}

Step 4 – Client Code


package com.codekatha;

class DIDemo {

    public static void main(String[] args) {

        Database database = new MySQLDatabase();
        UserService service = new UserService(database);
        service.saveUser();
    }
}

Now we can easily change the database without modifying UserService.

What We Achieved Using Dependency Injection

Loose coupling between classes
Easy to change implementations
Better testability
Follows Dependency Inversion Principle

Types of Dependency Injection

Constructor Injection (Recommended)

Dependencies are provided through constructor.

Ensures required dependency
Immutable design possible
Most preferred approach

Setter Injection

Dependencies are provided using setter methods.


public void setDatabase(Database database) {
    this.database = database;
}

Useful for optional dependencies.

Field Injection

Dependency is injected directly into fields (commonly used in Spring).

This approach is not recommended in plain Java due to testing issues.

Dependency Injection vs Factory Pattern

Factory creates objects.
Dependency Injection provides objects.

Factory handles creation logic, while DI handles dependency management.

Dependency Injection vs Service Locator

Dependency Injection → Dependencies provided externally.
Service Locator → Class requests dependencies itself.

Advantages of Dependency Injection

Reduces tight coupling
Improves maintainability
Enhances testability
Supports flexible design
Follows SOLID principles

Disadvantages of Dependency Injection

More configuration required
Slightly complex setup
Harder to understand for beginners

When Should You Use Dependency Injection

When building large applications
When multiple implementations exist
When writing testable code
When following SOLID principles

Real-World Usage of Dependency Injection

Spring Framework
Spring Boot applications
JUnit testing with mocks
Enterprise Java applications

Dependency Injection in Spring Framework

Spring provides automatic dependency injection using annotations.


@Autowired
private UserService userService;

The framework automatically provides the dependency.

Common Interview Questions on Dependency Injection

What is Dependency Injection?
Constructor vs Setter injection?
DI vs Factory pattern?
How DI supports loose coupling?

Simple Summary

Dependency Injection provides dependencies externally.
Reduces tight coupling.
Improves flexibility and testability.
Commonly used in Spring framework.

Conclusion

Dependency Injection is a powerful design principle that promotes flexible and maintainable application design. It removes dependency creation responsibility and allows systems to evolve easily.

Comments

Popular Posts on Code Katha

Java Interview Questions for 10 Years Experience

Sql Interview Questions for 10 Years Experience

Spring Boot Interview Questions for 10 Years Experience

Java interview questions - Must to know concepts

Visual Studio Code setup for Java and Spring with GitHub Copilot

Spring AI with Ollama

Data Structures & Algorithms Tutorial with Coding Interview Questions

Spring Data JPA

Topological Sort in Graph

Bit Manipulation and Bit Masking Concepts