[스프링 핵심원리 기본편] 7.5 ⚠️조회빈이 2개 있을 때 상황 + 해결 방법

코린이서현이·2023년 11월 13일
0

😨들어가면서😨

헉 이제 규칙적인 생활해야지
오늘 8강까지 듣고, 한언사 수업도 듣고 해야하는데...?? 

컴연방은 차근히 목요일까지 듣도록하고,,, 🥲 일단 강의부터 집중하자...

🎯 목표

📌 조회 빈이 두개 있을 때
📌 의존 관계 자동 주입에서 해결하는 방법

📌 조회 빈이 두개 있을 때

💭 음...? 왜 조회빈이 두개나 있을까?

  • @Autowired는 타입으로 빈을 조회하게 된다.

상황 1.

@Autowired
private DiscountPolicy discountPolicy; 
//DIP를 따르기 위해 구체 클래스가 아닌 인터페이스에 의존

➡️ 따라서 구체 클래스가 아닌, 인터페이스로 조회하게 된다.
⚠️ 이때 인터페이스를 구현한 빈이 두개 이상인 경우를 생각해보자.

//DiscountPolicy → 구현:  FixDiscountPolicy , RateDiscountPolicy

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

@Component
public class RateDiscountPolicy implements DiscountPolicy {}

상황 2.

AutoAppConfig.class ➡️ 컴포넌트 스캔 ! 
DiscountPolicy → 구현:  FixDiscountPolicy , RateDiscountPolicy

💻 실행화면
➡️ ⚠️ 오류 메시지

org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'orderServiceImpl' defined in file [C:\Users\USER\OneDrive - 
pusan.ac.kr\core\core\out\production\classes\hello\core\order\OrderServiceImpl.class]: 
Unsatisfied dependency expressed through constructor parameter 1; nested exception 
is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 'hello.core.discount.DiscountPolicy' available: 
expected single matching bean but found 2: fixDiscountPolicy,rateDiscountPolicy

🙆 해결방법

1. 스프링 빈을 수동 등록
2. 의존 관계 자동 주입에서 해결하는 방법

📌 의존 관계 자동 주입에서 해결하는 방법

🔨 @Autowired 필드 명

📒 매칭과정

  • @Autowired타입 매칭을 시도
  • 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다.

기존 코드

@Autowired
private DiscountPolicy discountPolicy

필드 명을 빈 이름으로 변경..

@Component
public class OrderServiceImpl implements  OrderService{

  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;

  public OrderServiceImpl(MemberRepository memberRepository, 
  					      DiscountPolicy rateDiscountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = rateDiscountPolicy;
  }

😀 "오~ 여러빈이 있군! 그러면 파라미터명으로 빈을 찾아야겠어~"

🤔 그러면 DIP에 위배되는거 아닌가..?

🔨 @Qualifier@Qualifier 끼리 매칭 → 빈 이름 매칭

  • @Qualifier : 구분할 수 있는 추가적인 옵션을 하나 제공하는 것이다. ( 빈 이름을 바꾸는 것 ❌)
  • 👎단점 ) 모든 코드에 붙여야한다.

✔️ 타입이 중복되는 빈에 @Qualifier("이름")설정

@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {
@Qualifier("mainDiscountPolich")
public class RateDiscountPolicy implements DiscountPolicy {

✔️ 등록하는 빈에 @Qualifier("이름")설정

@Component
public class OrderServiceImpl implements  OrderService{

  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;

  public OrderServiceImpl(MemberRepository memberRepository, 
  			@Qualifier("mainDiscountPolich") DiscountPolicy discountPolicy) { //추가
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
  }
  • 위의 예제는 컴포넌트 자동 주입의 예제이다. 그러나 빈 등록 시에도 동일하게 사용할 수 있따.

  • 해당 이름을 못찾으면, 해당이름을 가진 스프링 빈을 추가로 찾는다.
    그러나 이런식으로 사용하기 보다는, 명확하게 사용하는 것이 좋다.
    🙆 다시 상기하자! 명확하지 않은 코드는 짜지말자!!

➡️ 해결 완료~! 🙆
😀 "오~ @Qualifier("이름")을 보고 등록하면 되겠군~ "

🔨 @Primary

👏 자주 사용하는 방법?

  • 우선순위를 통해서 지정된다.
  • 중복되는 코드 하나에만 @Primary 예약어를 붙이면 된다.
  • 메인 DB 연결이 있을 때, 간단하게 할 수 있다.

@Primary : 예약어 사용

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {
}

등록하는 코드 - 아무것도 안붙여도 됨. 🙅

@Component
public class OrderServiceImpl implements  OrderService{

  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;

}

➡️ 해결 완료~! 🙆

우선순위@Primary vs @Qualifier

➡️ 자세한 것 > 덜 상세한 것
따라서@Qualifier이 우선순위가 높다.

😨마무리하면서😨

요새 계속 배가 아프다... 
profile
24년도까지 프로젝트 두개를 마치고 25년에는 개발 팀장을 할 수 있는 실력이 되자!

1개의 댓글

comment-user-thumbnail
2023년 11월 13일

정리가 잘 된 글이네요. 도움이 됐습니다.

답글 달기