일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Today
- Total
- Spring
- docker
- Servlet Filter
- 스프링 Configuration
- 라즈베리파이4
- 빈 중복 오류
- 스프링 싱글톤
- springsecurity
- 스프링 빈
- 도커
- 의존관계 주입
- 라즈베리파이
- 객체지향
- UsernamePasswordAuthenticationFilter
- Spring interceptor
- beandefinition
- 스프링
- ComponentScan
- Autowired 옵션
- 스프링 빈 조회
- RequiredArgsConstructor
- 스프링 컨테이너
- 롬복 Qualifier
- autowired
- DI컨테이너
- qualifier
- DI
- 생성자 주입
- 싱글톤 컨테이너
- HandlerMethodArgumentResolver
그날그날 공부기록
Map, List에 빈 주입 & 사용하기 본문
지금까지 했던 예제 코드에서는 하나의 빈을 필드에 주입받아 사용했다.
하지만 여러 개의 빈을 주입받아 사용해야 한다면 어떻게 해야 할까?
예를 들어 여러 개의 할인방식(bean) 중 하나를 유저가 선택해야 하는 상황이라면 관련 빈들을 모두 가져와 컴파일 시점이 아닌 실행 시에 동적으로 할인 방식을 선택해야 한다.
고정 할인방식인 fixDiscount와 비율 할인방식인 rateDiscount가 있다고 생각해보자.
@Component
public class FixDiscountPolicy implements DiscountPolicy{}
@Component
public class RateDiscountPolicy implements DiscountPolicy{}
두 개의 빈은 모두 스프링 컨테이너에 등록이 된다.
하지만 DiscountPolicy 타입의 필드에 주입받으려 하면 해당 타입의 빈이 중복으로 존재하므로 에러가 난다.
해당 빈을 모두 주입받으려면 Map이나 List를 사용하면 된다.
@Component
public class DiscountService{
private final Map<String, DiscountPolicy> policyMap;
private final List<DiscountPolicy> policyList;
@Autowired
public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policyList){
this.policyMap = policyMap;
this.policyList = policyList;
System.out.println("policyMap = " + policyMap);
System.out.println("policyList = " + policyList);
}
}
객체에 Map과 List를 선언하고 생성자에서 DiscountPolicy타입 빈들을 주입받는다.(fixDiscountPolicy, rateDiscountPolicy)
출력 결과는 다음과 같다.
policyMap = {fixDiscountPolicy=hello.core.discount.FixDiscountPolicy@31add175, rateDiscountPolicy=hello.core.discount.RateDiscountPolicy@ae3540e}
policyList = [hello.core.discount.FixDiscountPolicy@31add175, hello.core.discount.RateDiscountPolicy@ae3540e]
Map은 <String, DiscountPolicy>이므로 key(빈 이름)=value(인스턴스)형식으로 출력된다.
List는 인스턴스만 출력된다.
주입받은 빈들을 활용하여 할인코드(빈 이름)에 따라 할인방식을 선택하고, 해당 방식의 할인 가격을 반환하는 로직을 작성하였다.
public int discount(Member member, int price, String discountCode){
DiscountPolicy discountPolicy = policyMap.get(discountCode);
System.out.println("discountCode = " + discountCode);
System.out.println("discountPolicy = " + discountPolicy);
return discountPolicy.discount(member, price); //할인 가격 반환
}
policyMap.get()
을 통해 메서드에 입력받은 할인 코드에 따라 Map에 있는 빈을 가져온다.
DiscountPolicy.discount()
는 할인 가격을 반환한다.
작성한 코드를 테스트하기 위해 테스트 코드를 작성했다.
public class AllBeanTest {
@Test
void findAllBean(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);
//코드에 따라 할인방식을 변경하는 메서드가 있는 DiscountService 빈을 가져온다.
DiscountService discountService = ac.getBean(DiscountService.class);
//멤버를 설정한다.
Member member = new Member(1L, "userA", Grade.VIP);
//fixDiscountPolicy로 고정 할인을 선택한다.(고정 할인가격은 1000원이다.)
int discountPrice = discountService.discount(member, 10000, "fixDiscountPolicy");
assertThat(discountService).isInstanceOf(DiscountService.class);
assertThat(discountPrice).isEqualTo(1000); //반환되는 할인 가격이 1000원인지 확인.
//rateDiscountPolicy로 비율 할인을 선택한다.(할인 비율을 10%이다.)
int rateDiscountPrice = discountService.discount(member, 20000, "rateDiscountPolicy");
assertThat(rateDiscountPrice).isEqualTo(2000); //반환되는 할인 가격이 2000원인지 확인.
}
}
테스트는 통과하고 discount()가 실행되며 다음과 같은 출력 결과가 나온다.
의도대로 할인 정책을 선택하여 적용할 수 있었다.
스프링을 사용하니 다형성을 활용하여 간단하게 전략 패턴을 사용할 수 있었다.
잘 알아두면 비슷한 상황에서 편리하게 문제를 해결할 수 있을 것 같다.
출처
'Spring 공부' 카테고리의 다른 글
스프링 시큐리티 로그인 동작 따라가보기 (2) | 2023.09.25 |
---|---|
빈 생명주기, 콜백 이용하기 (0) | 2022.08.16 |
Qualifier을 대체할 수 있는 커스텀 애노테이션 만들기 (0) | 2022.08.09 |
스프링 빈 중복 시 오류 & 해결방법 (0) | 2022.08.02 |
lombok(롬복) 설치 & 적용하기 (0) | 2022.08.02 |