Programming/Spring

Class 형태로 Bean 접근 방법

khj1999 2025. 2. 6. 20:47

context.getBean(MyService.class)와 같이 클래스 타입으로 빈을 가져올 때, 같은 타입의 빈이 여러 개 등록되어 있다면 스프링은 어떤 빈을 반환해야 할지 몰라 NoUniqueBeanDefinitionException을 발생시킨다.

이를 해결하는 방법은 여러 가지가 있다.


1. @Primary 사용

가장 기본적인 해결책은 @Primary 애너테이션을 사용하여 우선순위를 지정하는 방법.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

    @Bean
    @Primary  // 기본 빈으로 설정
    public MyService myService1() {
        return new MyService();
    }

    @Bean
    public MyService myService2() {
        return new MyService();
    }
}

💡 결과: context.getBean(MyService.class)를 호출하면 myService1이 반환된다.


2. @Qualifier 사용 (빈 이름 지정)

@Qualifier를 이용하여 어떤 빈을 사용할 것인지 명시적으로 지정할 수도 있다.

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Qualifier("specialService")
public class SpecialService extends MyService {
}

이제 빈을 가져올 때 @Qualifier("specialService")를 사용하면 된다.

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

        MyService myService = context.getBean("specialService", MyService.class);
        myService.sayHello();
    }
}

💡 결과: "specialService"로 지정한 빈을 가져옴.


3. 빈 이름을 명시적으로 사용

context.getBean("beanName", MyService.class)을 사용하면 특정 이름을 가진 빈을 가져올 수 있다.

MyService myService = context.getBean("myService1", MyService.class);

💡 결과: "myService1" 이름의 빈을 가져옴.


4. Map을 사용하여 모든 빈을 가져오기

만약 같은 타입의 모든 빈을 가져와야 한다면, Map<String, MyService> 형태로 가져와 사용할 수도 있다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;

@Component
public class MyServiceConsumer {

    private final Map<String, MyService> myServices;

    @Autowired
    public MyServiceConsumer(Map<String, MyService> myServices) {
        this.myServices = myServices;
    }

    public void printServices() {
        myServices.forEach((name, service) -> {
            System.out.println("Bean Name: " + name);
            service.sayHello();
        });
    }
}

💡 결과: Map을 사용하여 등록된 모든 MyService 빈을 가져와 출력.


정리

해결 방법 설명

@Primary 기본 빈을 하나만 지정
@Qualifier 특정한 빈을 명확히 지정
context.getBean("이름") 빈 이름을 직접 지정
Map<String, Bean> 같은 타입의 모든 빈 가져오기

가장 간단한 해결책은 @Primary 또는 @Qualifier를 사용하는 것이다