@Autowired 애너테이션은 기본적으로 타입으로 빈을 조회합니다.

마치 getBean(Discount.class) 메서드를 호출하여 빈을 조회하는 것과 같습니다. 따라서, 위의 경우처럼 해당 빈의 타입이 2개 이상인 경우 스프링의 입장에서는 어떤 구현 객체가 들어와야 하는지 알 수 있는 방법이 없어 오류가 발생합니다.

물론, 참조 변수의 타입을 하위 구현 객체의 타입으로 변경할 수 있겠지만, 이 또한 구체적인 객체에 의존하는 결과를 초래하게 되어 객체지향적 설계의 원칙에 위배되는 것이기 때문에 권장되는 방식이 아닙니다.

그렇다면 어떻게 이 문제를 해결할 수 있을까요?

스프링은 크게 3가지의 해결 방법을 제공하고 있습니다.

  1. @Autowired 필드명 매칭
  2. @Qualifier 사용
  3. @Primary 사용

1. @Autowired 필드명 매칭

가장 손쉬운 방법으로는 필드명을 활용한 매칭 방법이 있습니다. @Autowired는 먼저 타입으로 빈을 조회하고, 만약 2개 이상의 여러 개의 빈이 있는 경우에 필드명 또는 매개변수명으로 빈을 매칭합니다.

하지만 해당 방법은, 필드 주입을 사용해야 하므로 실무에선 사용하지 않습니다.

2. @Qualifier 사용

두 번째 방법으로 @Qualifier를 사용하는 방법이 있습니다. 추가적인 구분자를 통해 의존 관계를 연결하는 방식입니다. 바로 코드를 통해 확인해 보겠습니다.

먼저 FixedAmountDiscountPolicy와 FixedRateDiscountPolicy 클래스에 @Qualifier 애너테이션을 통해 구분자를 지정해 줍니다.

@Component
@Qualifier("fixedAmount")
public class FixedAmountDiscountPolicy implements DiscountPolicy {

	--- 생략 ---

}