Spring/스프링 핵심 원리 - 기본편

[의존 관계 자동 주입] 조회할 빈이 2개 이상일 때

alsruds 2023. 12. 22. 03:10
🧐강의🧐
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard

 

  1. @Autowired : 필드명 매칭하기
  2. @Qualifier : 추가 구분자 생성하기
  3. @Primary : 우선 순위 정하기

 

🚨문제 상황🚨

🐶 @Autowired : 타입(Type)으로 조회 시 대상 빈이 2개 이상일 때 문제 발생

 

TEST

☑️ RateDiscountPolicy & FixDiscountPolicy 모두 @Component 적용하기

 

· 기존 코드 : RateDiscountPolicy 에만 적용되어 있는 @Component

...
@Component
public class RateDiscountPolicy implements DiscountPolicy{...}

 

· 변경 사항 : FixDiscountPolicy 에 @Component 애노테이션 추가

...
@Component
public class FixDiscountPolicy implements DiscountPolicy{...}

 

➡️ 의존 관계 자동 주입 실행 시 오류 발생 (NoUniqueBeanDefinitionException)

 

💡해결 방법💡

1. @Autowired 필드명 매칭하기

✅ 매칭 순서 : 타입(Type) → (결과가 2개 이상일 때) → 필드명 / 파라미터명

 

· 기존 코드 : OrderServiceImpl

...
@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

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

    ...
}

 

· 변경 사항 : 필드명을 빈 이름으로 변경 (rateDiscountPolicy)

...
@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy rateDiscountPolicy; // <--- 변경

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

    ...
}

 

2. @Qualifier 추가 구분자 붙이기

(+) 빈 이름을 변경하는 방법이 아님

✅ 동작 순서 : @Qualifier 끼리 매칭 → 빈 이름 매칭 → NoSuchBeanDefintionException 예외 발생

 

· 빈 등록 시 @Qualifier 추가 : RateDiscountPolicy & FixDiscountPolicy

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

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

 

· 생성자 자동 주입 시 구분자 지정 : OrderServiceImpl

...
@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

    ...
}

 

3. @Primary 우선 순위 정하기

✅ @Autowired 로 여러 빈 매칭 시, @Primary 가 붙어있는 빈이 우선

 

· 빈 등록 시 우선권 부여

//RateDiscountPolicy
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy{...}

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

 

 

@Primary vs. @Qualifier
- 우선 순위 : @Primary (기본값) < @Qualifier (상세값)
- @Primary : 메인 데이터베이스 연결

- @Qualifier : 서브 데이터베이스 연결
- @Qualifier 단점 : 주입 시 해당 애노테이션을 모든 코드에 붙여주어야 함