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를 이용하여 호출
- 상속 관계를 이용하여 호출