/ SPRING

Spring Bean 조회하기

Spring Container에서 Bean을 조회하는 방법을 정리합니다

Spring Bean이란?

Spring 공식 문서에서 Bean을 아래처럼 설명합니다.

A Spring IoC container manages one or more beans. These beans are created with the configuration metadata that you supply to the container (for example, in the form of XML definitions).

Spring IoC(Inversion Of Control) Container, 줄여서 Spring Container에서 관리하고 있는 객체들을 Bean이라고 부릅니다. Bean을 정의하기 위해서는 annotation(@bean)을 사용하거나 혹은 XML 파일 형식으로 정의할 수 있습니다.

@Configuration
    static class TestBeanConfig {
        @Bean
        public MemberRepository memberRepository() {
            return new MemoryMemberRepository();
        }

        @Bean
        public MemberService memberService() {
            return new MemberService();
        }
    }

Bean 호출하기

실제로 Bean을 호출하여 사용하는 방법은 아래와 같습니다.

  • Baen 이름으로 조회하기
  • 클래스로 조회하기
  • 상속 관계 조회하기

Bean 이름으로 조회하기

가장 기본적인 Bean 호출 방식입니다.

// Bean 호출을 위한 context 생성
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestBeanConfig.class);

MemberRepository bean1 = ac.getBean("memberRepository", MemberRepository.class);
MemberService bean2 = ac.getBean("memberService", MemberService.class);

memberRepository, memberService와 같이 Bean Name을 이용하여 조회할 수 있습니다. Bean Name은 생성할 때 따로 지정하지 않으면 기본값으로 method name을 사용합니다. @Bean 어노테이션 사용 시에 따로 bean name을 지정할 수도 있습니다.

        @Bean(name="memberService1")
        public MemberService memberService() {
            return new MemberService();
        }

클래스로 조회하기

Name이 아니라 bean의 class만으로도 조회가 가능합니다.

MemberRepository bean1 = ac.getBean(MemberRepository.class);

class만으로 Bean을 조회하는 경우 동일한 class를 가진 bean이 있다면 에러가 발생합니다.

@Configuration
    static class TestBeanConfig {
        @Bean
        public MemberRepository memberRepository1() {
            return new MemoryMemberRepository();
        }

        @Bean
        public MemberRepository memberRepository2() {
            return new MemoryMemberRepository();
        }
    }
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestBeanConfig.class);

MemberRepository bean1 = ac.getBean(MemberRepository.class); // 에러 발생
org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 'hello.demo.member.MemberRepository' available:
expected single matching bean but found 2: memberRepository1,memberRepository2

위 코드에서 MemberRepository.class에 해당하는 Bean이 2개(memberRepository1, memberRepository2)가 있으므로 NoUniqueBeanDefinitionException 에러가 발생합니다.

이런 경우 bean name을 정확히 지정해주거나, 모든 bean을 조회하고 싶다면 getBeansOfType 메소드를 사용해야합니다.

// bean name 지정하여 조회
MemberRepository bean1 = ac.getBean('memberRepository1', MemberRepository.class);

Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class); // memberRepository1, memberRepository2

상속 관계를 이용하여 조회하기

클래스 A를 상속받아 클래스 B를 선언했다면, 부모 클래스(A)를 이용하여 자식 클래스를 모두 조회할 수도 있습니다.

@Configuration
    static class TestConfig {
        @Bean
        public DiscountPolicy rateDiscountPolicy() {
            return new RateDiscountPolicy();
        }

        @Bean
        public DiscountPolicy fixDiscountPolicy(){
            return new FixDiscountPolicy();
        }
    }

DisCountPolicy를 상속받아 RateDiscountPolicy, FixDiscountPolicy 클래스를 선언했습니다.

부모 클래스를 이용하여 조회하는 경우 자식 클래스를 모두 조회할 수 있습니다. 1개 Bean만을 조회하기 위해 getBean을 사용하는 경우에는 마찬가지로 NoUniqueBeanDefinitionException 에러가 발생합니다.

DiscountPolicy bean1 = ac.getBean(DiscountPolicy.class); // NoUniqueBeanDefinitionException 에러 발생

Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class); // RateDiscountPolicy, FixDiscountPolicy

특정 자식 클래스를 조회하고 싶은 경우 Bean name을 이용해야합니다.

DiscountPolicy bean = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);

권장하는 방법은 아니지만, 특정 자식 클래스를 이용하여 조회할 수도 있습니다.

DiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);

정리

  • Bean은 Spring container에서 관리하는 객체이다.
  • container 내부의 bean을 호출하는 방법은 3가지가 있다.
    • Bean Name을 이용하여 호출
    • Class를 이용하여 호출
    • 상속 관계를 이용하여 호출

[참고]
[inflearn]스프링 핵심 원리 - 기본편
[Spring]Bean Overview