Map<Key, Interface>를 이용한 스프링 빈 활용

Map과 List를 사용하면 스프링 bean에 등록된 구현체(인터페이스를 implements한 클래스들)들을 조회할 수 있다.

기본 모양은 이렇다.

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;
            this.policies = policies;
            System.out.println("policyMap = " + policyMap);
            System.out.println("policies = " + policies);
}

DiscountService의 policyMap에 주입된 <빈이름, 빈이름에 해당하는 빈>을 통해

discount 메소드에서 입력된 discountCode String을 파라미터로 넘겨 String에 맞는 빈을 찾아서 실행

  • Map<String, T> policyMap : Key(String)에 스프링 빈 이름(BeanDefinitionName), Value(T) 해당 빈 이름과 매칭되는 T가 담긴다.
  • List<T> : T타입으로 조회한 모든 스프링 빈이 담긴다.

이런 걸 어따 써먹을 수 있을까?

 

여러가지 작업장이 있다고 가정해보자.

작업장들마다 특징은 다르겠으나, 공통적으로 반드시 해야만하는 일들이 있다.

예를 들어 출근카드 찍기, 퇴근카드 찍기.

모든 업장이 공통적으로 수행할 것이 분명한 업무들을 모아놓은 목차, 그것이 인터페이스이다.

 

이 인터페이스를 구현한 구현체를 서비스라고 해보자. @Service 어노테이션이 붙어있다.

이 어노테이션에는 name=""을 등록할 수 있다.

이 때 업장코드를 name으로 등록하고

path variable로 업장코드를 받는다면

요청 request가 들어왔을 때 spring이 알아서 해당하는 업장의 서비스를 bean으로 제공할 것이다.


아래는 path variable로 인터페이스 구현체를 가져오는 예시이다.

public class MainClass {

    private Map<String, SayHelloService> sayHelloService; // Map에 인터페이스를 타입으로 지정할 수 있다.

    public void HelloController(Map<String, SayHelloService> sayHelloService) {
        this.sayHelloService = sayHelloService;
    }

    @GetMapping("/hello/{lang}")
    public String sayHello(@PathVariable String lang) {
        String msg = this.sayHelloService.get(lang).sayHello(); // path variable을 키값으로 하여 원하는 인터페이스의 메서드를 가져온다.
        return msg;
        /*
        ENG 일 경우 hello
        SPN 일 경우 hola
         */
    }
}

Controller

 

public interface SayHelloService {
    String sayHello();
}

인터페이스

@Service("ENG")
public class SayHelloInEnglish implements SayHelloService {

    @Override
    public String sayHello() {
        return "hello";
    }
}

구현체1

@Service("SPN")
public class SayHelloInSpanish implements SayHelloService {

    @Override
    public String sayHello() {
        return "hola";
    }
}

구현체2