πŸ”₯ Launch Offer: Interview Preparation Bundle @ β‚Ή2,499 β‚Ή9,999 β€’ 75% OFF. Offer expires in πŸ”₯ Launch Offer: Interview Preparation Bundle @ β‚Ή2,499 β‚Ή9,999 β€’ 75% OFF. Offer expires in Interview Preparation Bundle @ β‚Ή2,499 β‚Ή9,999

00:00:00 Get Bundle
home spring boot why-constructor-injection-is-better-than-field-injection-in-spring-boot
Interview guide Spring Boot 30 sections

Why Constructor Injection is Better Than Field Injection in Spring Boot?

Constructor Injection and Field Injection are two common ways to inject dependencies in Spring Boot. While both achieve dependency injection, Constructor Injection is widely recommended by the Spring…

Start reading
By javainterviewprep July 29, 2026 7 min read

Constructor Injection and Field Injection are two common ways to inject dependencies in Spring Boot. While both achieve dependency injection, Constructor Injection is widely recommended by the Spring team because it creates fully initialized objects, makes dependencies explicit, supports immutability, and detects configuration problems during application startup. In this article, we’ll explore why Constructor Injection is considered a best practice, compare it with Field Injection, and understand the differences through simple examples and real-world analogies.

NOTE: Spring verifies the required bean at application startup (runtime)

Constructor Injection in Spring Boot: Why Mandatory Dependencies Should Always Use Constructors

When you start learning Spring Boot, you’ll encounter multiple ways to inject dependencies into a class:

  • Constructor Injection βœ… (Recommended)
  • Field Injection (@Autowired) ❌ (Not Recommended)
  • Setter Injection (For Optional Dependencies)

Many developers memorize that “Constructor Injection is the best practice.”

But the real question is:

Why?

The answer has very little to do with Spring and a lot to do with Object-Oriented Programming, Java, and building valid objects.

Let’s understand this from scratch.

What is Dependency Injection?

Imagine you’re creating a service responsible for managing products.

@Service
public class ProductService {

}

Can this service directly access the database?

No.

It needs another class that communicates with the database.

@Repository
public class ProductRepository {

}

Now, ProductService depends on ProductRepository.

ProductService
       β”‚
       β–Ό
ProductRepository

This relationship is called a dependency.

What is a Mandatory Dependency?

Some dependencies are absolutely required.

Without them, the class simply cannot perform its job.

For example:

ProductService
       β”‚
       β–Ό
ProductRepository

If there is no repository,

  • products cannot be saved
  • products cannot be updated
  • products cannot be deleted
  • products cannot be searched

So the repository is mandatory.

Constructor Injection

The recommended approach is:

@Service
public class ProductService {

    private final ProductRepository repository;

    public ProductService(ProductRepository repository) {
        this.repository = repository;
    }
}

Notice two important things.

1. The dependency is final

private final ProductRepository repository;

A final field can be assigned only once.

After the object is created, nobody can accidentally replace it.

This makes your class immutable with respect to its required dependency.

2. The constructor requires the dependency

public ProductService(ProductRepository repository) {
    this.repository = repository;
}

The constructor is saying:

“I cannot create a ProductService unless someone gives me a ProductRepository.”

This is a contract.

Real-Life Example: Buying a Car

Imagine you’re buying a car.

A car consists of:

Car
 β”œβ”€β”€ Engine (Mandatory)
 β”œβ”€β”€ Steering (Mandatory)
 β”œβ”€β”€ Wheels (Mandatory)
 └── Music System (Optional)

Can a car be manufactured without an engine?

No.

Can it run without steering?

No.

Can it exist without a music system?

Yes.

The engine and steering are mandatory dependencies.

The music system is an optional dependency.

Similarly,

ProductService
       β”‚
       β–Ό
ProductRepository

Without the repository, the service is incomplete.

How Spring Creates the Object?

Suppose your application starts.

Spring scans your project.

Spring Boot Application
        β”‚
        β–Ό
Find @Service
        β”‚
        β–Ό
Find ProductService

Spring notices that ProductService has a constructor.

public ProductService(ProductRepository repository)

Now Spring asks:

“To create ProductService, I first need ProductRepository.”

So the process becomes:

Spring Container
        β”‚
        β–Ό
Create ProductRepository
        β”‚
        β–Ό
Pass Repository to Constructor
        β”‚
        β–Ό
Create ProductService
        β”‚
        β–Ό
Application Ready

Every dependency is resolved before the object is created.

What Happens If the Repository Doesn’t Exist?

Suppose you accidentally delete:

@Repository
public class ProductRepository {

}

Now Spring tries to create ProductService.

Need ProductService
        β”‚
        β–Ό
Need ProductRepository
        β”‚
        β–Ό
Bean Found?
        β”‚
      No
        β”‚
        β–Ό
Startup Failed

Spring immediately throws an error:

Parameter 0 of constructor in ProductService
required a bean of type
'ProductRepository'
that could not be found.

The application never starts.

At first, this might seem annoying.

In reality, it’s one of Spring’s biggest strengths.

Why Is Failing Fast a Good Thing?

Imagine an Inventory Management System.

ProductService
      β”‚
      β”œβ”€β”€ ProductRepository
      β”œβ”€β”€ CategoryRepository
      └── InventoryRepository

Suppose InventoryRepository is missing.

You have two possible situations.

Option A

The application starts.

Everything appears normal.

One hour later,

a customer clicks:

Add Product

Your code executes:

repository.save(product);

Boom.

NullPointerException

The customer sees an error.

Your production application crashes.

Option B

The application refuses to start.

Spring displays:

No qualifying bean of type
ProductRepository found.

The application never goes live.

You fix the issue immediately.

No customer is affected.

Failing at startup is much safer than failing in production.

Now Compare with Field Injection

Many beginners write:

@Service
public class ProductService {

    @Autowired
    private ProductRepository repository;
}

It looks shorter.

It looks cleaner.

But something very important is hidden.

Java Automatically Creates a Default Constructor

Since no constructor is written,

Java provides one automatically.

Conceptually:

public ProductService() {

}

Now Java allows this:

ProductService service = new ProductService();

The object has been created successfully.

But notice the problem.

repository == null

Spring has not injected anything yet.

What Happens Next?

Suppose someone writes:

ProductService service = new ProductService();

service.saveProduct(product);

Inside:

repository.save(product);

Since repository is null,

Java throws:

NullPointerException

The object existed,

but it was incomplete.

Why Doesn’t This Happen with Constructor Injection?

Look again.

public class ProductService {

    private final ProductRepository repository;

    public ProductService(ProductRepository repository) {
        this.repository = repository;
    }
}

Now try this:

new ProductService();

Java immediately stops you.

Constructor ProductService(ProductRepository)
cannot be applied to given types.

The compiler refuses to create an invalid object.

This protection comes from Java itself, not Spring.

Constructor Injection Enforces Valid Objects

Think about it.

With field injection:

Create Object
      β”‚
      β–Ό
Inject Dependency Later

There is a time when the object exists,

but its dependency is still null.

With constructor injection:

Need Dependency
      β”‚
      β–Ό
Create Object

The dependency comes first.

The object is born fully initialized.

Visual Comparison

Constructor Injection

Need ProductService
        β”‚
        β–Ό
Need ProductRepository
        β”‚
        β–Ό
Repository Available?
        β”‚
    Yes ─────────► Create ProductService
        β”‚
    No ──────────► Startup Failed

There is no possibility of an invalid object.

Field Injection

Create ProductService
        β”‚
        β–Ό
repository = null
        β”‚
        β–Ό
Inject Later

If something goes wrong before injection,

the object is already in an invalid state.

Another Real-Life Example

Imagine a restaurant.

The chef needs:

  • Stove
  • Gas
  • Cooking utensils

Can the chef start cooking without a stove?

No.

The restaurant owner would never hire a chef and say:

“We’ll install the stove later.”

Instead,

the kitchen is prepared first,

then the chef starts working.

Constructor injection follows the same principle.

The service is created only after all required resources are available.

Advantages of Constructor Injection

1. Prevents NullPointerException

Dependencies are guaranteed to exist before the object is created.

2. Supports Immutable Objects

private final ProductRepository repository;

The dependency cannot be changed accidentally.

3. Makes Dependencies Explicit

Anyone reading the constructor immediately knows what the class needs.

public ProductService(ProductRepository repository)

The required dependency is obvious.

4. Enables Fail-Fast Startup

Configuration problems are detected when the application starts, not when users are interacting with it.

5. Easier Unit Testing

Testing becomes straightforward because dependencies can be supplied directly.

ProductRepository repository = Mockito.mock(ProductRepository.class);

ProductService service =
        new ProductService(repository);

No Spring container is required.

Since Spring Framework 4.3, if a class has only one constructor, you don’t even need @Autowired.

@Service
public class ProductService {

    private final ProductRepository repository;

    public ProductService(ProductRepository repository) {
        this.repository = repository;
    }
}

Spring automatically uses that constructor.

This keeps the code cleaner and emphasizes constructor injection as the preferred approach.

Constructor vs Field Injection

Constructor InjectionField Injection
Dependency required before object creationDependency injected after object creation
Prevents invalid objectsObject can exist with null dependencies
Supports final fieldsCannot use final fields
Easy to unit testDifficult to test without reflection or Spring
Dependencies are explicitDependencies are hidden
Detects missing beans during startupCan lead to runtime NullPointerException
Recommended by SpringGenerally discouraged for required dependencies

Key Takeaways

  • Use Constructor Injection for mandatory dependencies.
  • A constructor defines the minimum requirements needed to create a valid object.
  • Java prevents creating the object without those required dependencies.
  • Spring resolves all constructor dependencies before instantiating the bean.
  • If a dependency is missing, Spring fails the application startup immediately, helping you catch configuration issues early.
  • Constructor injection works naturally with final fields, immutability, and unit testing.
  • Field injection may appear simpler, but it can create objects in an invalid state and makes testing and maintenance harder.

Rule of Thumb: If your class cannot function without a dependency, make it a constructor parameter. Let Java and Spring enforce that rule for you.