쌓고 쌓다
@Autowired 조회 빈이 2개 이상일때 해결 방법 본문
OrderServiveImpl
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
@Autowired는 타입으로 조회하기에 아래와 유사하다.
ac.getBean(DiscountPolicy.class);
DiscountPolicy 타입으로 조회시 자식 타입도 함께 조회되기에 FixDiscountPolicy, RateDiscountPolicy가 함께 조회된다.
빈이 2개이상 조회가 되어 생성자 @Autowired에서 문제가 발생한다.
여기서 하위 타입인 FixDiscount, RateDiscoun로 지정하여 스프링 빈을 가져올 수 있지만.
역할과 구현의 분리 DIP가 위반된다. 우리는 DiscountPolicy에 의존해야지 구현체인 FixDiscount, RateDiscount에 의존하면 안된다.
해결 방법 3가지를 알아보자.
RateDiscountPolicy를 주입하길 원한다고 가정한다.
1. 필드명 매칭
@Autowired 아래의 과정으로 매칭한다.
- 타입 매칭
- 타입 매칭시 2개 이상 빈이 나오면 필드 명, 파라미터 명으로 매칭
필드 명으로 해결
@Autowired
private DiscountPolicy rateDiscountPolicy;
/*
기존
@Autowired
private DiscountPolicy discountPolicy;
*/
파라미터 명으로 해결
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = rateDiscountPolicy;
}
DiscountPolicy로 타입 매칭을 시도했으나 2개이상 빈이 존재하므로
파라미터명인 rateDiscountPolicy와 일치하는 빈을 찾아 주입한다.
2. @Qualifier
@Qualifier는 추가 구분자를 만드는것이지 빈 이름을 변경하는 방법이 아니다.
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 MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
주입시 @Qualifier에 등로간 추가 구분자 이름을 적어준다.
3. @Primary
@Primary를 통해 우선순위를 지정할 수 있다.
@Autowired시 빈이 여러개 조회 될 경우 @Primary가 우선권을 가진다.
@Primary 적용
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy{ ... }
@Component
public class FixDiscountPolicy implements DiscountPolicy{ ... }
@Autowired 주입
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
DiscountPolicy 타입으로 여러개 빈이 조회되었지만 @Primary가 붙은 RateDiscountPolicy가 우선순위를 갖는다.
@Primary, @Qualifier 활용
자주 사용하는 메인 DB의 커넥션을 획득하는 스프링 빈은 @Primary로 @Qualifier 없이 편히 조회하고,
가끔 사용하는 서비 DB의 커넥션을 획득하는 스프링 빈은 @Qualifier를 통해 명시적으로 획득하게하면 코드가 깔끔.
@Priamry와 @Qualifier를 동시에 사용한다면 어떤것이 우선순위를 가질까?
@Priamry는 기본값처럼 동작하고 @Qualifier는 사용자가 세세하게 지정한다.
스프링은 자동보단 수동이, 넓은 범위보단 좁은 범위가 우선 순위가 더 높다.
=> @Qualifier가 우선순위이다.
'프로그래밍 > spring' 카테고리의 다른 글
빈 생명주기 콜백 (0) | 2023.07.16 |
---|---|
[스프링 부트] 게시글 검색 - 11 (0) | 2023.07.15 |
의존관계 주입 방법 4가지 (0) | 2023.07.14 |
컴포넌트 스캔과 의존관계 주입 (0) | 2023.07.13 |
[스프링 부트] 댓글 삭제 및 댓글 개수 - 10 (0) | 2023.07.13 |