Spring : 동일 타입 여러 스프링 빈 주입 받기

    Spring : 동일 타입 여러 스프링 빈 주입 받기

    OCP를 지키기 위한 수단 중 하나로 인터페이스를 도입한다. 인터페이스를 도입하면 객체 사이의 결합이 낮춰진다는 장점이 있다. 그런데 이것은 동일한 인터페이스를 갖지만 서로 다른 구현체를 가지는 스프링 빈을 여러 개 등록하고 사용할 때는 꽤 귀찮은 상황이 될 수도 있다. 

    스프링은 기본적으로 타입을 보고 스프링 빈을 주입해준다. 동일한 타입의 스프링 빈이 여러가지 존재한다면 필드의 이름과 스프링 빈의 이름이 일치하는 것을 넣어준다. 그래도 잘 안된다면 ObjectProvider 등을 이용해서 넣는 방법이 있다. 이 때 필드의 이름을 직접 지정하거나, ObjectProvider에 이름을 직접 지정해야하기 때문에 하드코딩에 조금쯤은 가까운 방법이 되기도 한다. 

    public class FakerNameFactory implements FakerFactory{
    
        private final Faker faker = new Faker();
        private final Name factory = faker.name();
    
        public String firstName() {
            return factory.firstName();
        }
    
        public String lastName() {
            return factory.lastName();
        }
    
        public String username() {
            return factory.username();
        }
    
        public String name() {
            return factory.name();
        }
    
    }
    
    public class FakerNumberFactory implements FakerFactory{
    
        private final Faker faker = new Faker();
        private final Number factory = faker.number();
    
        public Integer age() {
            return factory.numberBetween(0, 100);
        }
    
        public Double price() {
            return factory.randomDouble(2, 0, 100000);
        }
    
        public Long largeLongNumber() {
            return factory.numberBetween(0L, 9876543210L);
        }
    
        public Double largeDoubleNumber() {
            return factory.randomDouble(2, 0L, 9876543210L);
        }
    }

    예를 들어 위 두 클래스가 존재하는 경우를 생각해보자. 모두 FakerFactory의 구현체다. 이 녀석들을 스프링 빈으로 등록하고, FakerFactory 인터페이스 타입으로 스프링 빈을 주입받게 되면 문제가 발생한다. 스프링 입장에서는 FakerFactory에 Compatiable한 스프링 빈이 2개 등록되어 있고, fakerFactory라는 필드 이름에 맞는 스프링 빈을 선정할 수 없기 때문이다.

    @Component
    @RequiredArgsConstructor
    public class FactoryDirector {
    
    	// 스프링 부팅 시 에러 발생함. (어떤 스프링 빈을 주입해야할지 모르기 때문)
        private final FakerFactory fakerFactory;
    }

    위와 같은 문제가 발생했을 때, Iterable한 객체 타입으로도 스프링 빈을 주입 받을 수 있다. List 클래스로 주입받고자 하는 스프링 빈의 타입을 선언해주면 스프링은 해당 타입에 맞는 스프링 빈을 자동으로 DI 해준다. 특정한 스프링 빈만 주입받고 싶을 때는 사용할 수 없는 방법이지만, 등록된 모든 스프링 빈을 받아서 처리해야하는 로직이 있다면 다음 방법을 고려해볼 수 있다.

    @Component
    @RequiredArgsConstructor
    public class FactoryDirector {
    
        private final List<FakerFactory> factories;
    }

     

    댓글

    Designed by JB FACTORY