같은 타입의 Bean이 두 개일 때

마라탕천재 ㅣ 2024. 8. 25. 18:04

1. 같은 타입 Bean 등록

Food를 상속받은 Chicken과 Pizza 클래스를 빈으로 등록한다.

  • Food 클래스
public interface Food {
    void eat();
}
  • Chicken 클래스
@Component
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}
  • Pizza 클래스
@Component
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}
  • 테스트 코드 작성

같은 타입의 빈이 두 개라서 다음과 같이 오류가 발생할 것이다.

Autowired를 통해 의존성을 주입하려고 시도하고있으나, 빈으로 등록된 Chicken과 Pizza중 어떤 클래스를 주입해야 할 지 몰라서 발생하는 오류이다.

@SpringBootTest
public class BeanTest {

    @Autowired
    Food food;
    
}

 

 

2. Bean 이름 명시

빈 이름을 명시하면 해결할 수 있다.

단, 이 경우에 주입받는 객체의 이름은 해당 클래스명을 캐멀케이스 방식으로 작성해야 한다.

  • 테스트 코드 변경
@SpringBootTest
public class BeanTest {

    @Autowired
    Food pizza;
    
    @Autowired
    Food chicken;
    
    @Test
    void test1() {
        pizza.eat();
        chicken.eat();
    }
}

 

 

3. @Primary 어노테이션 이용

  • Chicken 클래스에 @Primary어노테이션 추가
  • 테스트 코드 변경
@SpringBootTest
public class BeanTest {

    @Autowired
    Food food;

    @Test
    void test1() {
        food.eat();
    }
}

@Primary가 추가되면 같은 타입의 Bean이 여러 개 있더라도 우선 @Primary가 설정된 Bean 객체를 주입해준다.

 

 

4. @Qualifier 어노테이션 이용

  • Pizza 클래스에 @Qualifier 어노테이션 추가
@Component
@Qualifier("pizza")
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}
  • 테스트 코드 변경
@SpringBootTest
public class BeanTest {

    @Autowired
    @Qualifier("pizza")
    Food food;

    @Test
    @DisplayName("Primary 와 Qualifier 우선순위 확인")
    void test1() {
        // 현재 Chicken 은 Primary 가 적용된 상태
        // Pizza는 Qualifier 가 추가된 상태입니다.
        food.eat();
    }
}

 Qualifier는 적용하기 위해서 주입 받고자하는 곳에 해당 Qualifier를 추가한다.

같은 타입의 Bean들에 Qualifier와 Primary가 동시에 적용되어있다면 Qualifier의 우선순위가 더 높다.

따라서, 같은 타입의 Bean이 여러 개 있을 때는 범용적으로 사용되는 Bean 객체에는 Primary를 설정하고 지엽적으로 사용되는 Bean 객체에는 Qualifier를 사용하는 것이 좋다.