Skip to main content

Dependency Injection Basics

A simple Spring Boot project demonstrating the basics of Dependency Injection (DI) using Person and Pet (Cat and Dog) examples.

Step 1: Setup your Project​

Create a new Spring Boot project using Spring Initializr with:

  • Spring Web dependency
  • Spring Boot Devtools dependency (allows hot reloading)
  • Java version 17 or higher
  • Maven project

Step 2: Initial Implementation​

Create the following initial classes and interfaces:

Pet.java​

public interface Pet {
void feed();
}

Cat.java​

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class Cat implements Pet {
private static final Logger logger = LoggerFactory.getLogger(Cat.class);

@Override
public void feed() {
logger.info("Feeding the cat... ");
}
}

Person.java​

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class Person {
private static final Logger logger = LoggerFactory.getLogger(Person.class);
private final Pet pet;

public Person(Pet pet) {
this.pet = pet;
}

public void feedPet() {
logger.info("Feeding the pet...");
pet.feed();
}
}

Step 3: Run Your Application​

Update your main application to use CommandLineRunner:

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class LabOneDemoApplication {

public static void main(String[] args) {
SpringApplication.run(LabOneDemoApplication.class, args);
}

@Bean
public CommandLineRunner demo(Person person) {
return args -> {
person.feedPet();
};
}
}

Run your application:

./mvnw spring-boot:run

Lab Extension Task: Adding a Dog​

Task Instructions:​

  • Add a new class Dog that implements the Pet interface.
  • Annotate it correctly so Spring recognizes it.
  • Rerun your application. Observe what happens.
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class Dog implements Pet {
private static final Logger logger = LoggerFactory.getLogger(Dog.class);

@Override
public void feed() {
logger.info("Feeding the dog...");
}
}

Issue and Task: Resolving Bean Ambiguity​

When you run the application after adding Dog, you will encounter an issue:

Field pet in Person required a single bean, but 2 were found: cat, dog.

Task:​

  • Research and apply the correct annotation (@Qualifier) to explicitly define which pet implementation (Cat or Dog) should be injected.
  • Run the application again and verify that the chosen pet feeds correctly.
@Component
public class Person {
private static final Logger logger = LoggerFactory.getLogger(Person.class);
private final Pet pet;

public Person(@Qualifier("dog") Pet pet) { // Use "cat" to inject Cat instead
this.pet = pet;
}

public void feedPet() {
logger.info("Feeding the pet...");
pet.feed();
}
}

Optional Advanced Task: Dynamic Pet Selection Service​

Task:​

  • Create a new service class (PetService) that returns either the Cat or Dog implementation based on a command-line argument.
  • Update your application to dynamically inject the chosen pet at runtime based on input arguments.
@Component
public class Person {
private static final Logger logger = LoggerFactory.getLogger(Person.class);
private final Pet pet;

public Person(Pet pet) { // Remove the qualifier for Pet
this.pet = pet;
}

public void feedPet() {
logger.info("Feeding the pet...");
pet.feed();
}
}
@SpringBootApplication
public class LabOneDemoApplication {

public static void main(String[] args) {
SpringApplication.run(LabOneDemoApplication.class, args);
}

@Bean
public CommandLineRunner demo(ApplicationContext context) {
return args -> {
String petType = args.length > 0 ? args[0] : "dog";
Pet pet = context.getBean(petType, Pet.class);
Person person = new Person(pet);
person.feedPet();
};
}
}

Example run command:

./mvnw spring-boot:run -Dspring-boot.run.arguments=dog

Verify the output dynamically changes depending on the provided argument.