스프링 빈 기본 조회

스프링 컨테이너에 실제 스프링 빈이 잘 등록되었는지 확인해보자.

public class ApplicationContextInfoTest {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

  @Test
  @DisplayName("모든 빈 출력하기")
  void findAllBean() {
    // 스프링에 등록된 모든 빈 이름을 조회한다.
    String[] beanDefinitionNames = ac.getBeanDefinitionNames();
    for (String beanDefinition : beanDefinitionNames) {
      // 빈 이름으로 빈 객체(인스턴스)를 조회한다.
      Object bean = ac.getBean(beanDefinition);
      System.out.println("beanDefinition = " + beanDefinition + ", object = " + bean);
    }
  }
}

스프링 컨테이너에 있는 모든 빈 정보가 출력되었다.

public class ApplicationContextInfoTest {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

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

      // ROLE_APPLICATION: 직접 등록한 애플리케이션 빈
      // ROLE_INFRASTRUCTURE: 스프링 내부에서 사용하는 빈
      if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
        Object bean = ac.getBean(beanDefinitionName);
        System.out.println("name = " + beanDefinitionName + ", object = " + bean);
      }
    }
  }
}

스프링 내부에서 쓰는 빈은 제외하고 내가 직접 등록한 빈만 출력할 수도 있다.

ac.getBean(빈 이름, 타입);
ac.getBean(타입);

스프링 컨테이너에서 스프링 빈을 찾는 가장 기본적인 조회 방법은 위와 같다. 조회 대상 스프링 빈이 없으면 NoSuchBeanDefinitoinException: No bean named '***' available 예외가 발생한다.

빈 이름으로 조회

public class ApplicationContextBasicFindTest {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

  @Test
  @DisplayName("빈 이름으로 조회")
  void findBeanByName() {
    MemberService memberService = ac.getBean("memberService", MemberService.class);
    System.out.println("memberService = " + memberService);
    System.out.println("memberService.getClass() = " + memberService.getClass());

    assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
  }
}

memberService빈을 불러와 MemberServiceImpl의 인스턴스라는 것을 확인했다.

이름 없이 타입으로 조회

public class ApplicationContextBasicFindTest {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

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

구체 타입으로 조회

public class ApplicationContextBasicFindTest {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

  @Test
  @DisplayName("구체 타입으로 조회")
  void findBeanByName2() {
    // 기본적으로 인터페이스로 조회하면 인터페이스의 구현체가 조회 대상이 된다.
    // 그래서 이렇게 직접 구현체로 빈을 가져올 수도 있다.
    MemberService memberService = ac.getBean(MemberServiceImpl.class);
    assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
  }
}

memberServiceAppConfig에서 MemberService를 반환한다고 메서드가 정의되어 있어도, 실제로는 MemberServiceImpl라는 인스턴스 타입을 보고 결정하기 때문에 구체 클래스로도 조회할 수 있다.

하지만 이 방법은 좋지 않다. 역할과 구현을 구분하고 역할에 의존해야 하기 때문이다.

존재하지 않는 빈 조회

public class ApplicationContextBasicFindTest {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

  @Test
  @DisplayName("빈 이름으로 조회 실패")
  void findBeanByNameFail() {
    assertThrows(NoSuchBeanDefinitionException.class,
        () -> ac.getBean("없는 빈", MemberServiceImpl.class));
  }
}

Last updated