DEV Community

Abhishek Tiwari
Abhishek Tiwari

Posted on

1

Spring Boot Learning Series – Part 1: Understanding Dependency Injection

Image description

πŸ”Œ What is Dependency Injection (DI)?

Dependency Injection is a design pattern where the dependencies (objects your class needs to work) are provided to the class, instead of the class creating them itself.

🚫 Without DI:

public class Car {
    private Engine engine = new Engine(); // tightly coupled
}
Enter fullscreen mode Exit fullscreen mode

βœ… With DI:

public class Car {
    private Engine engine;

    public Car(Engine engine) { // injected from outside
        this.engine = engine;
    }
}
Enter fullscreen mode Exit fullscreen mode

🌱 How DI Works in Spring Boot

  • Dependency Injection means Spring gives your class what it needs, instead of you writing code to create those things yourself.
  • Spring Boot has a built-in system called the IoC Container (ApplicationContext) that manages your objects (called beans) and connects them automatically.
  • This makes your code cleaner, easier to change, and easier to test.

πŸ” IoC vs πŸ”Œ DI

Concept Description
Inversion of Control (IoC) A general principle where control of object creation and flow is inverted β€” instead of you creating objects, a container/framework does it for you.
Dependency Injection (DI) specific implementation of IoC where dependencies are provided (injected) to a class, rather than the class creating them itself.

🀝 Relationship:

  • DI is one way to achieve IoC.
  • Spring uses IoC Container to inject dependencies (DI) into your classes.

Real-life analogy:

Imagine you’re baking a cake. Instead of making your own eggs, sugar, and flour from scratch, a chef (Spring) delivers these ingredients to your kitchen exactly when you need them.

Why use DI?

  • You don’t hardcode dependencies, so you can swap or change implementations easily.
  • It promotes loose coupling between classes.
  • It makes unit testing easier because you can inject mocks or stubs.

Common ways to inject dependencies in Spring Boot:

1. Field Injection (Not recommended for production but simple)

@Component
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void registerUser(User user) {
        userRepository.save(user);
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Spring injects UserRepository instance into the field.

2. Constructor Injection (Recommended!)

@Component
public class UserService {

    private final UserRepository userRepository;

    @Autowired  // Optional on single constructor since Spring 4.3+
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void registerUser(User user) {
        userRepository.save(user);
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Spring injects UserRepository via constructor.
  • Easier to test and better for immutability.

3. Setter Injection

@Component
public class UserService {

    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void registerUser(User user) {
        userRepository.save(user);
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Spring calls the setter method to inject the dependency.

πŸ”„ Techniques to Swap/Change Dependencies

1. Multiple Beans + @Qualifier

@Component("petrol")
public class PetrolEngine implements Engine {}

@Component("diesel")
public class DieselEngine implements Engine {}
Enter fullscreen mode Exit fullscreen mode
@Autowired
@Qualifier("diesel")
private Engine engine;
Enter fullscreen mode Exit fullscreen mode

2. Profile-Based Beans (@Profile)

@Component
@Profile("dev")
public class DevEngine implements Engine {}

@Component
@Profile("prod")
public class ProdEngine implements Engine {}
Enter fullscreen mode Exit fullscreen mode

Set active profile in application.properties:

spring.profiles.active=prod
Enter fullscreen mode Exit fullscreen mode

3. Custom Configuration with @Bean

@Configuration
public class EngineConfig {
    @Bean
    public Engine engine() {
        return new PetrolEngine(); // or new DieselEngine();
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Conditional Beans (@ConditionalOn...)

Use Spring Boot's conditional annotations to load a bean only under specific conditions.

The property engine.type is checked in your application.properties

@Bean
@ConditionalOnProperty(name = "engine.type", havingValue = "diesel")
public Engine dieselEngine() {
    return new DieselEngine();
}
Enter fullscreen mode Exit fullscreen mode

🧠 Summary

  • DI = Don’t create dependencies yourself, let Spring give them to you
  • Makes code loosely coupled and easier to test
  • Swap dependencies using:

    βœ… @Qualifier

    βœ… @Profile

    βœ… Custom @Bean config

    βœ… Conditional beans

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

πŸ‘‹ Kindness is contagious

Explore this insightful write-up embraced by the inclusive DEV Community. Tech enthusiasts of all skill levels can contribute insights and expand our shared knowledge.

Spreading a simple "thank you" uplifts creatorsβ€”let them know your thoughts in the discussion below!

At DEV, collaborative learning fuels growth and forges stronger connections. If this piece resonated with you, a brief note of thanks goes a long way.

Okay