본문 바로가기

Spring

Spring- 조회한 빈이 모두 필요할 때(Map, List)

Map과 List를 사용해서 여러가지 스프링 빈 받아오기

 예를 들어서 DiscountPolicy들 중에서 FixDiscountPolicy, RateDiscountPolicy가 모두 필요한 경우가 존재할 수도 있다. 

기존 방법으로는 하나의 DiscountPolicy만 주입받아서 사용할 수 있었지만 Map과 List를 사용한다면 여러 DiscountPolicy를 필요에 따라서 받아 사용할 수 있다. 

 

package hello.core.autowired;

import java.util.List;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

public class AllBeanTest {
    ApplicationContext ac                           
            = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);

    @Test
    void findAllBean(){
        DiscountService discountService = ac.getBean(DiscountService.class);

        Member member = new Member(1L, "userA", Grade.VIP);

        //fixDiscountPolicy를 적용했을 때 discountPrice
        int fixDiscountPrice = discountService.discount(member, 20000, "fixDiscountPolicy");
        //rateDiscountPrice를 적용했을 때 discountPrice
        int rateDiscountPrice = discountService.discount(member, 20000, "rateDiscountPolicy");

        assertThat(discountService).isInstanceOf(DiscountService.class);
        assertThat(fixDiscountPrice).isEqualTo(1000);
        assertThat(rateDiscountPrice).isEqualTo(2000);
    }

    static class DiscountService{
        // Map과 List를 사용함으로써 동적으로 빈을 선택할 수 있다.
        private final Map<String, DiscountPolicy> policyMap;  // Map에 DiscountPolicy 빈들을 넣어놓음.
        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);
        }
    }
}


policyMap = {fixDiscountPolicy=hello.core.discount.FixDiscountPolicy@3f390d63, rateDiscountPolicy=hello.core.discount.RateDiscountPolicy@74a6a609}
policies = [hello.core.discount.FixDiscountPolicy@3f390d63, hello.core.discount.RateDiscountPolicy@74a6a609]

 ApplicationContext 객체 ac를 생성하는 부분(line 10)을 보면 구성정보 클래스로 AutoAppConfig.class 하나가 아닌 DiscountService.class도 들어가는 것을 알 수 있다. 즉 ac를 등록할 때는 한번에 여러개의 구성정보 클래스 등록이 가능하다.

 또한 AutoAppConfig를 통해서 fixDiscountPolicy와 rateDiscountPolicy이 컴포넌트 스캔되어 빈으로 등록된다. 그렇게 등록된 두개의 DiscountPolicy 빈들은 생성자 주입을 통해서 DiscountService 클래스의 Map과 List 필드로 주입된다. 

 주입된 빈들은 필요에 따라서 get() 메소드를 사용해 Map에서 꺼내어 사용하면 된다.