Bean 등록 - 같은 타입이 2개일 경우

박영준·2023년 6월 27일
0

Spring

목록 보기
26/58

1. 기본 상황

  • 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("피자를 먹습니다.");
    }
}

2. 잘못된 사용

BeanTest 클래스

public class BeanTest {

	@Autowired
    Food food;		// 에러
}
  • 원인
    • Food 타입의 Bean 객체가 하나 이상 있기 때문 (Chicken, Pizza)
    • food 필드에 Bean을 주입해줄 때, 같은 Food 타입의 Bean 객체가 하나 이상이므로 어떤 Bean을 등록해줘야할지 모르기 때문

3. 해결법

방법 1 : 이름 명시하기

BeanTest 클래스

@SpringBootTest
public class BeanTest {

    @Autowired
    Food pizza;		// Bean 이름 : pizza
    
    @Autowired
    Food chicken;		// Bean 이름 : chicken
    
}
  • @Autowired
    • 기본적으로 : Bean Type(Food)으로 DI 를 지원
    • 연결이 되지 않을 경우 : Bean Name(pizza, chicken)으로 찾음 --> 방법 1

방법 2 : @Primary

Chicken 클래스

@Component
@Primary
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}

BeanTest 클래스

@SpringBootTest
public class BeanTest {
    @Autowired
    Food food;
}
  • @Primary 을 추가할 경우
    같은 타입의 Bean이 여러개 있더라도, 우선 @Primary가 설정된 Bean 객체를 주입

@Primary 사용 상황
같은 타입의 Bean이 여러 개 있을 때,
범용적으로 사용되는 Bean 객체에는 @Primary를 설정

방법 3 : @Qualifier

Pizza 클래스

@Component
@Qualifier("pizza")
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

BeanTest 클래스

@SpringBootTest
public class BeanTest {

    @Autowired
    @Qualifier("pizza")		// pizza 객체를 여기에 주입 -> 주입하고자하는 필드에도 @Qualifier("pizza") 를 추가
    Food food;
}

@Qualifier 사용 상황
Qualifier 를 적용하기 위해서는 주입받을 곳에 일일이 @Qualifier를 반드시 추가해야한다.
지엽적으로 사용되는 Bean 객체에는 @Qualifier를 설정

4. @Primary vs @Qualifier 우선순위

Chicken 클래스

@Component
@Primary
public class Chicken implements Food {
    @Override
    public void eat() {
        System.out.println("치킨을 먹습니다.");
    }
}

Pizza 클래스

@Component
@Qualifier("pizza")
public class Pizza implements Food {
    @Override
    public void eat() {
        System.out.println("피자를 먹습니다.");
    }
}

BeanTest 클래스

@SpringBootTest
public class BeanTest {

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

    @Test
    @DisplayName("Primary 와 Qualifier 우선순위 확인")
    void test1() {
        // 현재 Chicken 은 Primary 가 적용된 상태
        // Pizza는 Qualifier 가 추가된 상태입니다.
        food.eat();
    }
}
  • 현재 상황 : 같은 타입의 Bean들에 Qualifier와 Primary가 동시에 적용된 상황

    • Chicken 클래스에는 @Primary, Pizza 클래스에는 @Qualifier 가 걸려있다
    • Chicken 과 Pizza 는 같은 Food 타입이다

    이땐, Qualifier의 우선순위가 더 높다. (Qualifier 의 결과값이 반환됨)

profile
개발자로 거듭나기!

0개의 댓글