Dependency Injection Explained with Spring

Dependency Injection Explained with Spring Framework

🔰 What is Dependency Injection (DI)?

Dependency Injection is a design pattern used to remove tight coupling between objects.
It helps make code easier to test, maintain, and scale.

In simple words:

👉 Instead of a class creating its own dependencies, they are given (injected) to it from outside.


🎯 Why Use Dependency Injection?

Without DI:


class Car { Engine engine = new Engine(); // tightly coupled }

With DI:


class Car { private Engine engine; public Car(Engine engine) { this.engine = engine; // engine is injected } }

✅ Loose coupling
✅ Easy to test
✅ Better flexibility
✅ Supports modular code


🧰 What is Spring Framework?

Spring is a powerful Java framework for building web apps and enterprise-level software.

It provides built-in support for Dependency Injection using:

  • XML configuration

  • Annotations

  • Java-based configuration


🔧 Types of Dependency Injection in Spring

Spring supports:

1. Constructor Injection

Dependencies are passed through the class constructor.

2. Setter Injection

Dependencies are injected via public setter methods.

3. Field Injection (less recommended)

Dependencies are directly injected into class fields using @Autowired.


📦 Example: Constructor Injection with Spring

Step 1: Create the Dependency Class


public class Engine { public void start() { System.out.println("Engine started!"); } }

Step 2: Create the Dependent Class


public class Car { private Engine engine; public Car(Engine engine) { this.engine = engine; } public void drive() { engine.start(); System.out.println("Car is moving..."); } }

Step 3: Create Spring Configuration (Java-based)


import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class AppConfig { @Bean public Engine engine() { return new Engine(); } @Bean public Car car() { return new Car(engine()); } }

Step 4: Create the Main Class


import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); Car car = context.getBean(Car.class); car.drive(); } }

✅ Output:


Engine started! Car is moving...

📝 Setter Injection Example


public class Car { private Engine engine; public void setEngine(Engine engine) { this.engine = engine; } public void drive() { engine.start(); System.out.println("Car is driving..."); } }

In AppConfig:


@Bean public Car car() { Car car = new Car(); car.setEngine(engine()); return car; }

🧠 When to Use Which?

TypeUse When...
Constructor InjectionDependency is required, and should not change
Setter InjectionDependency is optional or may change later
Field InjectionAvoid in large projects (hard to test and manage)

🛠 Using Annotations for DI

Spring provides easy annotations for DI.


@Component public class Engine { public void start() { System.out.println("Engine started!"); } }

@Component public class Car { @Autowired private Engine engine; public void drive() { engine.start(); System.out.println("Car is running..."); } }

In MainApp:


@ComponentScan("com.example") @Configuration public class AppConfig { } public class MainApp { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); Car car = context.getBean(Car.class); car.drive(); } }

🔄 DI vs Traditional Programming

FeatureWithout DIWith DI (Spring)
CouplingTightLoose
TestingHard (need real objects)Easy (can use mock objects)
FlexibilityLowHigh
MaintenanceMore effortEasier

✅ Benefits of Using Dependency Injection

  • Separation of concerns

  • Easier unit testing

  • Reusable and flexible components

  • Centralized configuration

  • Reduces boilerplate code with Spring


💡 Real-World Use Case

Imagine a web application with:

  • A UserService that needs a UserRepository

  • A UserController that needs the UserService

Instead of creating objects manually:


UserRepository repo = new UserRepository(); UserService service = new UserService(repo); UserController controller = new UserController(service);

Spring does all this for you automatically using DI.


🚀 Summary

Dependency Injection is a powerful way to build flexible and testable applications.

✅ Helps reduce tight coupling
✅ Makes testing easier
✅ Spring handles it automatically using annotations or config
✅ Use constructor injection for required dependencies
✅ Use setter injection for optional ones


Final Thought

If you want to build scalable, clean Java apps — Dependency Injection with Spring is a must-learn skill.



Read More 




Comments

Popular posts from this blog

What is WebDriver in Selenium? Explained with Java

Why Choose Python for Full-Stack Web Development

How Generative AI Differs from Traditional AI