Notice
«   2025/01   »
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
01-10 04:46
Today
Total
관리 메뉴

그날그날 공부기록

Map, List에 빈 주입 & 사용하기 본문

Spring 공부

Map, List에 빈 주입 & 사용하기

given_dragon 2022. 8. 9. 16:48

지금까지 했던 예제 코드에서는 하나의 빈을 필드에 주입받아 사용했다.

하지만 여러 개의 빈을 주입받아 사용해야 한다면 어떻게 해야 할까?

 

예를 들어 여러 개의 할인방식(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()가 실행되며 다음과 같은 출력 결과가 나온다.

의도대로 할인 정책을 선택하여 적용할 수 있었다.

 

스프링을 사용하니 다형성을 활용하여 간단하게 전략 패턴을 사용할 수 있었다.

잘 알아두면 비슷한 상황에서 편리하게 문제를 해결할 수 있을 것 같다.

 

 

 


출처

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

 

Comments