Full Stack • Java • System Design • Cloud • AI Engineering

Dependency Injection Pattern in Java

Learn Dependency Injection (DI) in Java with Constructor Injection, Setter Injection, Field Injection, Spring IoC Container, Bean Lifecycle, UML diagrams, enterprise examples, and interview questions.

What You Will Learn

  • What is Dependency Injection?
  • Why DI is Needed
  • Tight Coupling vs Loose Coupling
  • Types of Dependency Injection
  • Constructor Injection
  • Setter Injection
  • Field Injection
  • Spring IoC Container
  • Enterprise Use Cases
  • Benefits and Limitations
  • Interview Questions

Introduction

Almost every enterprise application contains dependencies.

Example:

OrderController

↓

OrderService

↓

OrderRepository

↓

Database

Without Dependency Injection:

public class OrderService {

    private OrderRepository repository =
            new OrderRepository();
}

Problems:

Tightly Coupled

Difficult Testing

Hard Maintenance

Poor Flexibility

Dependency Injection solves this problem.


What is Dependency Injection?

Dependency Injection is a design pattern where dependencies are provided from outside instead of being created inside the class.

Instead of:

OrderRepository repository =
        new OrderRepository();

Use:

OrderService(
        OrderRepository repository)

Dependency comes from outside.


Purpose of Dependency Injection

Primary Goal:

Loose Coupling

Better Testability

Better Maintainability

Real World Analogy

Think about a car.

Without DI:

Car Builds Its Own Engine

With DI:

Engine Is Provided

↓

Car Uses Engine

Car doesn't care who created the engine.


Problem Without DI

flowchart LR
    A[OrderService]
    B[OrderRepository]

    A --> B

OrderService creates repository itself.

Strong dependency.


Solution With DI

flowchart LR
    A[Spring Container]
    B[OrderService]
    C[OrderRepository]

    A --> B
    A --> C

Container injects dependencies.


Dependency Injection Architecture

flowchart LR
    A[Client]
    B[IoC Container]
    C[Service]
    D[Repository]

    A --> B
    B --> C
    B --> D

What Is A Dependency?

Example:

public class OrderService {

    private OrderRepository repository;
}

Dependency:

OrderRepository

because OrderService depends on it.


Tight Coupling Example

public class OrderService {

    private OrderRepository repository =
            new OrderRepository();

    public void createOrder() {

        repository.save();
    }
}

Problems:

Hard To Replace

Hard To Mock

Hard To Test

Loose Coupling Example

public class OrderService {

    private OrderRepository repository;

    public OrderService(
            OrderRepository repository) {

        this.repository = repository;
    }
}

Now dependency is injected.


Types of Dependency Injection

Constructor Injection

Setter Injection

Field Injection

Constructor Injection

Recommended approach.


Example

public class OrderService {

    private final OrderRepository repository;

    public OrderService(
            OrderRepository repository) {

        this.repository = repository;
    }
}

Flow

flowchart LR
    A[Container]
    B[Repository]
    C[OrderService]

    A --> B
    B --> C

Benefits

Immutable Objects

Easy Testing

Mandatory Dependencies

Setter Injection

Dependency injected using setter method.


Example

public class OrderService {

    private OrderRepository repository;

    public void setRepository(
            OrderRepository repository) {

        this.repository = repository;
    }
}

Flow

flowchart LR
    A[Container]
    B[Create Object]
    C[Call Setter]

    A --> B
    B --> C

Benefits

Optional Dependencies

Runtime Updates

Field Injection

Common but not recommended.


Example

@Service
public class OrderService {

    @Autowired
    private OrderRepository repository;
}

Issues

Hard Testing

Reflection Based

Hidden Dependencies

Comparison

Feature Constructor Setter Field
Recommended Yes Sometimes No
Testability Excellent Good Poor
Immutability Yes No No
Mandatory Dependency Yes No No

Inversion Of Control (IoC)

Dependency Injection is implemented using:

IoC Container

What Is IoC?

Traditional:

Application Controls Objects

IoC:

Container Controls Objects

IoC Flow

flowchart LR
    A[Application]
    B[IoC Container]
    C[Beans]

    A --> B
    B --> C

Spring IoC Container

Spring creates:

Beans

Dependencies

Object Lifecycle

automatically.


Bean Creation Flow

flowchart LR
    A[Application Start]
    B[Scan Components]
    C[Create Beans]
    D[Inject Dependencies]
    E[Ready]

    A --> B
    B --> C
    C --> D
    D --> E

Spring Example

Repository:

@Repository
public class OrderRepository {

}

Service:

@Service
public class OrderService {

    private final OrderRepository repository;

    public OrderService(
            OrderRepository repository) {

        this.repository = repository;
    }
}

Controller:

@RestController
public class OrderController {

    private final OrderService service;

    public OrderController(
            OrderService service) {

        this.service = service;
    }
}

Request Flow

flowchart LR
    A[Controller]
    B[Service]
    C[Repository]
    D[Database]

    A --> B
    B --> C
    C --> D

Bean Lifecycle

Create Bean

↓

Inject Dependencies

↓

Initialize

↓

Use Bean

↓

Destroy Bean

Bean Lifecycle Flow

flowchart LR
    A[Create]
    B[Inject]
    C[Initialize]
    D[Use]
    E[Destroy]

    A --> B
    B --> C
    C --> D
    D --> E

Banking Example

Fund Transfer System.

Dependencies:

TransferController

↓

TransferService

↓

AccountRepository

↓

Database

Banking Architecture

flowchart LR
    A[Transfer Controller]
    B[Transfer Service]
    C[Account Repository]
    D[Database]

    A --> B
    B --> C
    C --> D

Insurance Example

Claim Processing System.

Dependencies:

ClaimController

↓

ClaimService

↓

ClaimRepository

All injected by Spring.


Insurance Flow

flowchart LR
    A[Claim Controller]
    B[Claim Service]
    C[Claim Repository]

    A --> B
    B --> C

Unit Testing Example

Without DI:

OrderService service =
        new OrderService();

Difficult to mock.


With DI:

OrderRepository mockRepo =
        Mockito.mock(
                OrderRepository.class);

OrderService service =
        new OrderService(
                mockRepo);

Easy testing.


Testing Architecture

flowchart LR
    A[Test]
    B[Mock Repository]
    C[Service]

    A --> B
    B --> C

Enterprise Examples

Banking

Fund Transfer

Loan Processing

Account Management

Insurance

Claims

Policy Management

Premium Processing

Retail

Order Processing

Inventory Tracking

Healthcare

Patient Records

Appointment Systems

Spring Annotations

Common DI annotations:

@Component

@Service

@Repository

@Controller

@RestController

@Autowired

Benefits

✅ Loose Coupling

✅ Better Testing

✅ Easier Maintenance

✅ Flexible Architecture

✅ Improved Scalability

✅ Follows SOLID Principles


Limitations

❌ More Initial Setup

❌ Learning Curve

❌ Container Dependency


When To Use

Use DI when:

  • Building Enterprise Applications
  • Using Spring Framework
  • Large Team Development
  • Testability Is Important

When Not To Use

Avoid when:

  • Small Utility Programs
  • Simple Standalone Applications

Dependency Injection vs Factory Pattern

Feature Dependency Injection Factory
Creates Objects Container Factory
Dependency Management Yes No
Spring Usage Very High Moderate

Dependency Injection vs Service Locator

Feature DI Service Locator
Dependency Visibility Explicit Hidden
Testability High Medium
Recommended Yes No

Real Enterprise Architecture

flowchart LR
    A[Controller]
    B[Service]
    C[Repository]
    D[Database]

    A --> B
    B --> C
    C --> D

Interview Questions

What is Dependency Injection?

A design pattern where dependencies are provided externally instead of being created inside a class.


What is IoC?

Inversion of Control.

Container manages object creation.


Types of DI?

Constructor Injection

Setter Injection

Field Injection

Recommended Injection Type?

Constructor Injection

Why Constructor Injection?

Immutable

Testable

Mandatory Dependencies

Spring Container Example?

ApplicationContext

Main Benefit?

Loose coupling and improved testability.


Key Takeaways

  • Dependency Injection is one of the most important enterprise patterns.
  • Promotes loose coupling.
  • Makes testing easier.
  • Implemented by Spring IoC Container.
  • Constructor Injection is the preferred approach.
  • Foundation of Spring Framework architecture.
  • Used in Banking, Insurance, Retail, Healthcare, and almost every modern Java application.