스프링 공부 (인프런 김영한 선생님)/스프링 핵심원리

[스프링 핵심원리] 10. 조회된 빈이 모두 필요한 경우

ProgYun. 2023. 5. 15. 19:59

의도적으로 정말 해당 타입의 스프링 빈이 모두 필요한 경우가 생길 수 있다

-> 예를 들어, 할인과 관련된 서비스를 제공할 때 Client가 할인의 종류를 선택할 수 있다고 가정 (고정/비율)

 

스프링을 사용하는 경우 전략패턴을 매우 간단하게 구현할 수 있음

 

package hello.springintroduction.autowired;

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

import hello.AutoAppConfig;
import hello.springintroduction.Member.Grade;
import hello.springintroduction.Member.Member;
import hello.springintroduction.discount.DiscountPolicy;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

public class AllBeanTest {

    @Test
    void findAllBean(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(
            AutoAppConfig.class,
            DiscountService.class);

        DiscountService discountService = ac.getBean(DiscountService.class);
        Member member = new Member(1L, "userA", Grade.VIP);
        int discountPrice = discountService.discount(member, 10000, "fixDiscountPolicy");
        assertThat(discountService).isInstanceOf(DiscountService.class);
        assertThat(discountPrice).isEqualTo(1000);



        // AutoAppConfig에서 컴포넌트 스캔하면서 Rate, Fix DiscountPolicy를 스프링 빈으로 등록한다.

    }

    @Component
    static class DiscountService{
        private final Map<String, DiscountPolicy> policyMap;
        private final List<DiscountPolicy> policies;

        @Autowired
        public DiscountService(Map<String, DiscountPolicy> policyMap,
            List<DiscountPolicy> policies) {
            this.policyMap = policyMap; // Key Value
            this.policies = policies; // Value
            System.out.println("policyMap = " + policyMap);
            System.out.println("policies = " + policies);
            // 출력 결과 두 빈이 모두 등록됐으며 리스트로 등록되었음을 알 수 있다.
        }

        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);
        }
    }

}

참고로 타입이 같은 두 빈은 @Qualifer 또는 @Primary를 통해 우선순위나 빈이 지정되어 있는 상태에서 진행됨.

그렇지 않은 경우, 여기서도 NoUniqueBeanDefinition이 발생함.

 

전략패턴 구현을 위해 DiscountService에 Map과 List 형식으로 두 빈을 모두 가져온뒤

문자열을 통해 .get 한 이후, 해당 정책을 적용하는 과정을 거침