[Spring] @Qualifier @Primary

Seongho·2023년 2월 2일
0

Spring

목록 보기
10/13

빈 조회 시, 같은 타입이 두 개 이상일 때


@Autowired는 Type으로 스프링 빈을 조회한다. 따라서 applicationContext.getBean(DiscountPolicy.class)와 유사하게 동작한다. 그런데 DiscountPolicy 인터페이스의 구현클래스가 FixDiscountPolicy, RateDiscountPolicy 이렇게 두개가 있다면

@Component
public class FixDiscountPolicy implements DiscountPolicy {}
//
@Component
public class RateDiscountPolicy implements DiscountPolicy {}

NoUniqueBeanDefinitionException 예외가 발생한다.

@Autowired 필드명 매칭

@Autowired는 타입 매칭을 시도하고 여러 개의 빈이 있으면 필드 이름으로 빈 이름을 매칭한다. 따라서 필드명을 빈 이름으로 변경하면 된다.

@Qualifier

@Component가 있는 빈 등록 위치에 @Qualifier를 이용하여 이름을 적어준다.

@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy { ... }
//
@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy { ... }

@Qualifier 사용 시 애너테이션 만들기

@Qualifier는 문자열로 @Qualifier를 찾기 때문에 만약 @Qualifier("mmainDiscountPolicy") 이렇게 오타를 내면 컴파일 에러는 나지 않고 오류를 찾기 힘들다. 따라서 아래와 같이 애너테이션을 만들어서 사용하는게 일반적이다.


**무분별한 애너테이션 재정의는 유지보수에 방해가 된다.

@Primary

@Primary는 우선순위를 정하는 방법으로 @Autowired 시에 여러 빈이 매칭되면 @Primary가 있는 빈이 우선권을 가진다.

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy { ... }	//우선권 가짐
//
@Component
public class FixDiscountPolicy implements DiscountPolicy { ... }

DIP, OCP 위반에 대한 의문

위 세 가지 방법을 잘 살펴보면 세 방법 모두 필드에 DiscountPolicy라는 인터페이스에 의존하고 있기 때문에 DIP위반은 아니다. 하지만, 만약 RateDiscountPolicy에서 FixDiscountPolicy로 변경하게 된다면 코드의 수정이 일어나므로 OCP를 위반한다. SOLID원칙은 지키려고 노력해야 하는 것. 하지만 지키지 못할 상황도 있는 것이다.

@Primary, @Qualifier를 활용하기

위 세 가지 방법 중에 @Primary, @Qualifier를 적절히 섞어서 사용하는 것이 좋다.
어떤 메인으로 동작하는 것을 컨트롤 하는 빈이 있고, 코드에서 특별한 상황에 사용하는 빈이 있으면, 메인으로 사용되는 빈에 @Primary를 붙이고, 서브로 사용되는 빈에 @Qualifier("빈 이름")을 붙여서 명시적으로 사용해주면 된다. 참고로 @Primary보다 @Qualifier가 우선순위가 높다.

profile
Record What I Learned

0개의 댓글