A Beginner’s Guide to Spring Boot Dependency Injection with Qualifiers


18/05/25

5 mins

In modern Java development, Spring Boot stands out for its ability to reduce boilerplate and simplify configuration. One of its core strengths is how it manages object creation and dependency injection using interfaces and annotations.

In this blog post, we’ll look at a simple Spring Boot example that demonstrates how Spring uses dependency injection and Inversion of Control (IoC) to wire together components without manual instantiation. This setup uses one interface, three implementations, and an IoC-managed class that chooses which one to use based on annotations.


1. Overview of the Project Structure

The goal of this sample project is to simulate a course purchasing system with the following components:

  • ICourse — an interface representing a course.

  • JavaCourse, SpringBootCourse, and DevOpsCourse — three different course implementations.

  • College — a service class that depends on the ICourse interface.

  • SpringBoot02Application — the main application class that bootstraps the Spring context.


2. The Interface: ICourse

This interface defines the contract for any course service.

public interface ICourse { boolean purchase(double fee); }

3. The Implementations

Each course implements the ICourse interface and is marked with the @Component annotation so Spring can detect and register it as a bean.

JavaCourse.java

@Component("java") public class JavaCourse implements ICourse { public boolean purchase(double fee) { System.out.println("Java Course Purchased. Fee: ₹" + fee); return true; } }

SpringBootCourse.java

@Component("spring") public class SpringBootCourse implements ICourse { public boolean purchase(double fee) { System.out.println("Spring Boot Course Purchased. Fee: ₹" + fee); return true; } }

DevOpsCourse.java

@Component("devops") public class DevOpsCourse implements ICourse { public boolean purchase(double fee) { System.out.println("DevOps Course Purchased. Fee: ₹" + fee); return true; } }

4. The Dependency Injection Logic in College.java

This is where Spring's Dependency Injection kicks in. The College class depends on an ICourse implementation, and the actual implementation to inject is decided using the @Qualifier annotation.

@Component public class College { private ICourse course; @Autowired public College(@Qualifier("spring") ICourse course) { this.course = course; } public boolean buyTheCourse(double fee) { return course.purchase(fee); } }

Here, the @Qualifier("spring") ensures that Spring injects the SpringBootCourse bean.


5. Bootstrapping the Application: SpringBoot02Application.java

This is the main class where the Spring Boot application starts. It uses SpringApplication.run() to launch the application and get access to the application context.

@SpringBootApplication public class SpringBoot02Application { public static void main(String[] args) { ConfigurableApplicationContext container = SpringApplication.run(SpringBoot02Application.class, args); College college = container.getBean(College.class); boolean status = college.buyTheCourse(4545.4); if (status) System.out.println("Enrolled to Course"); else System.out.println("Failed to enroll"); } }

6. Sample Output

If the @Qualifier("spring") is used in College, the output will be:

Spring Boot Course Purchased. Fee: ₹4545.4 Enrolled to Course

7. Key Takeaways

  • Interface-Based Design: Promotes loose coupling and high flexibility.

  • Multiple Implementations: Can be easily managed and switched using @Qualifier.

  • Annotation-Driven Configuration: Removes the need for XML configuration files.

  • Spring Boot’s Simplicity: Automatically handles component scanning and dependency wiring, allowing developers to focus on business logic.


Conclusion

This example highlights the power of Spring Boot in managing dependencies and simplifying application architecture. By using interfaces, annotations, and Spring's IoC container, you can build clean, scalable applications that are easy to maintain and extend. Whether you're working on a microservice or a monolith, this pattern of interface-driven design with Spring Boot is a solid foundation.