- 항상 하나의 빈만 사용하는 것이 아니라, 클라이언트의 선택에 따라 여러 할인 정책(fix, rate)을 유연하게 적용해야 할 때가 있음
- 스프링은 전략 패턴(Strategy Pattern)을 구현할 수 있도록 특정 타입의 모든 빈을 List나 Map으로 주입받는 기능을 제공
1. 전체 빈 조회 테스트 코드
DiscountService는 모든 DiscountPolicy를 주입받아, 상황에 맞는 정책을 골라서 실행
package com.example.spring_study.autowired;
import com.example.spring_study.AutoAppConfig;
import com.example.spring_study.discount.DiscountPolicy;
import com.example.spring_study.member.Grade;
import com.example.spring_study.member.Member;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.*;
public class AllBeanTest {
@Test
void findAllBean(){
ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);
DiscountService discountSerivce = ac.getBean(DiscountService.class);
Member member = new Member(1L, "userA", Grade.VIP);
int discountPrice = discountSerivce.discount(member, 10000, "fixDiscountPolicy");
assertThat(discountSerivce).isInstanceOf(DiscountService.class);
assertThat(discountPrice).isEqualTo(1000);
int rateDiscountPrice = discountSerivce.discount(member, 20000, "rateDiscountPolicy");
assertThat(rateDiscountPrice).isEqualTo(2000);
}
static class DiscountService{
// Map으로 모든 DiscountPolicy를 받음
private final Map<String, DiscountPolicy> policyMap;
private final List<DiscountPolicy> policies;
public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policies) {
this.policyMap = policyMap;
this.policies = policies;
System.out.println("policyMap = " + policyMap);
System.out.println("policies = " + policies);
}
public int discount(Member member, int price, String discountCode) {
DiscountPolicy discountPolicy = policyMap.get(discountCode);
return discountPolicy.discount(member, price);
}
}
}
2. 로직 및 주입 분석
주입 방식
- Map<String, DiscountPolicy>: 키(key)에 스프링 빈의 이름이 들어가고, 값(value)에 해당 타입의 스프링 빈 객체가 담김
- List<DiscountPolicy>: 해당 타입으로 조회된 모든 스프링 빈을 리스트에 담아줌
- 만약 일치하는 타입의 빈이 하나도 없다면, 스프링은 에러를 내지 않고 빈 컬렉션이나 빈 Map을 주입
로직 분석
- discount() 메서드는 discountCode로 "fixDiscountPolicy"가 넘어오면 Map에서 해당 빈을 찾아 고정 할인 로직을 실행
- "rateDiscountPolicy"가 넘어오면 정률 할인 빈을 찾아 실행합니다. 이를 통해 다형성을 극대화한 전략 패턴을 구현할 수 있음
3. 참고: 컨테이너 생성과 동시에 빈 등록하기
new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class); 코드는 다음 두 가지를 동시에 수행
- AutoAppConfig.class: 설정 정보를 읽어 빈을 스캔하고 등록
- DiscountService.class: 해당 클래스를 스프링 컨테이너에 직접 스프링 빈으로 등록
요약
- 특정 타입의 빈이 모두 필요할 때는 List나 Map을 사용하면 매우 편리
- 스프링은 주입 시점에 해당 타입의 모든 빈을 자동으로 찾아 컬렉션에 채워줌.
- 이 방식은 동적인 선택권이 필요한 비즈니스 로직(다양한 결제 수단, 다양한 할인 정책 등)에서 강력한 힘을 발휘
'INFLEARN' 카테고리의 다른 글
| [스프링 핵심 원리 - 기본편] 17. 빈 스코프(Singleton, Prototype, Request, Proxy) (0) | 2026.03.24 |
|---|---|
| [스프링 핵심 원리 - 기본편] 16. 빈 생명주기 콜백 (0) | 2026.03.24 |
| [스프링 핵심 원리 - 기본편] 14. 애노태이션 직접 생성하기 (1) | 2026.03.21 |
| [스프링 핵심 원리 - 기본편] 13. 조회 Bean이 2개 이상일 경우(@Qualifier vs @Primary) (0) | 2026.03.20 |
| [스프링 핵심 원리 - 기본편] 12. Lombock 라이브러리 (0) | 2026.03.20 |