Spring - 스프링 컨테이너 생성과 Bean 등록

목차

스프링 컨테이너 생성 과정과 Bean 등록 과정

스프링 컨테이너를 생성할 때는 구성 정보를 지정해주어야 한다. 구성 정보는 클래스나 xml 을 이용해 정의할 수 있습니다.

//스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);

스프링 컨테이너 생성

스프링 컨테이너 생성시 설정 정보를 이용해 스프링 컨에티너를 생성합니다. 아래에서는 AppConfig.class 를 설정 정보로 이용해 스프링 컨테이너를 생성합니다.

스프링 빈 등록

스프링 컨테이너는 파라미터로 넘어온 설정 클래스 정보를 사용해서 스프링 빈을 등록한다. 아래에서는 AppConfig.class 애 정의된 객체를 Bean 으로 등록합니다.

스프링 빈 의존관계 설정 - 준비

스프링 빈 의존관계 설정 - 완료

등록된 모든 빈 확인

ApplicationContext 에 등록된 모든 Bean 을 조회하고 싶을 경우 ApplicationContext 객체의 getBeanDefinitionNames 메소드를 사용하면 됩니다.

@Test
@DisplayName("모든 빈 출력하기")
void findAllBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();

for(String beanDefinitionName : beanDefinitionNames){
Object bean = ac.getBean(beanDefinitionName);
System.out.println("bean = " + beanDefinitionName + " object = " + bean);
}
}

@Test
@DisplayName("애플리케이션 빈 출력하기")
void findApplicationBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();

for(String beanDefinitionName : beanDefinitionNames){
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);

if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + " object = " + bean);
}
}
}

컨테이너에 등록된 Bean 조회

컨테이너에 등록된 Bean 조회시 getBean 메소드를 사용합니다.

ApplicationContext 는 등록된 Bean 을 가져와 사용할 수 있게 getBean 메소드를 제공합니다. getBean 메소드를 통해 Bean 정보를 방법으로는 객체타입으로 조회하는 방법, 객체타입과 Bean 이름으로 조회하는 방법, 구체 객체타입으로 조회하는 방법이 있습니다.

@Test
@DisplayName("빈 이름으로 조회")
void findBeanByName(){
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}

@Test
@DisplayName("이름없이 타입으로 조회")
void findBeanByType(){
MemberService memberService = ac.getBean(MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}

@Test
@DisplayName("구체 타입으로 조회")
void findBeanByType2(){
MemberServiceImpl memberService = ac.getBean("memberService", MemberServiceImpl.class);
// 구체적으로 적는 것은 별로 않좋다.
// 될 수 있는한 추상화한 인터페이스에 테스트를 맞춘다.
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}

@Test
@DisplayName("빈 이름으로 조회X")
void findBeanByNameX(){
assertThatThrownBy(()->{
MemberService xxxxx = ac.getBean("xxxxx", MemberService.class);
}).isInstanceOf(NoSuchBeanDefinitionException.class);
}

Bean 의 동일한 타입이 둘 이상인 경우

같은 타입으로 등록된 빈이 여러개 있을 경우 getBean 을 이용해 Bean 을 가져오게 되면 NoUniqueBeanDefinitionException 에러가 발생하게 됩니다. 이때는 특정 Bean 을 가져올 수 있도록 등록된 Bean 이름 까지 같이 지정해주면 에러를 해결할 수 있습니다.

또한, ApplicationContext 에 특정 타입으로 등록된 모든 Bean 목록을 조회 하고 싶을 경우 ApplicationContext 객체의 getBeansOfType 메소드를 사용하면 됩니다.

같은 타입으로 여러개의 Bean 등록

memberRepository1 와 memberRepository2 가 ApplicationContext 에 MemberRepository 타입 Bean 으로 등록됩니다.

public class ApplicationContextExtendsFindTest {

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);

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

@Bean
public MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
}

같은 타입으로 여러개의 Bean 조회

@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류가 발생한다.")
void findBeanByTypeDuplicate(){
assertThatThrownBy(() ->{
ac.getBean(MemberRepository.class);
}).isInstanceOf(NoUniqueBeanDefinitionException.class);
}

@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 빈 이름을 지정하면 된다.")
void findBeanByName(){
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
assertThat(memberRepository).isEqualTo(MemberRepository.class);
}

@Test
@DisplayName("특정 타입을 모두 조회하기")
void findAllBeanByType(){
Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
for(String key : beansOfType.keySet()){
System.out.println("key = " + key + " value =" + beansOfType.get(key));
}

System.out.println("beansOfType = " + beansOfType);
assertThat(beansOfType.size()).isEqualTo(2);
}
Share