Spring/김영한 스프링 핵심원리 - 기본편

[섹션4-3] 스프링 빈 조회- 기본

보름달빵 2024. 2. 9. 18:17

 

스프링 빈을 조회하는 방법들에 대해서 알아보자 

 

스프링 컨테이너에서 스프링 빈을 조회하는 가장 기본적인 방법은

 getBean을 이용하는 것이다. 

 

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

 

 

  • ApplicationContextBasicFindTest 
public class ApplicationContextBasicFindTest {

    // 1. 기본적인 방법으로 빈 조회
    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("빈 이름으로 조회하기")
    void findBeanbyName(){
        MemberService memberService = ac.getBean("memberService", MemberService.class);
        Assertions.assertThat(memberService).isInstanceOf(MemberService.class);
        
        /*System.out.println("memberService = " + memberService);
         System.out.println("memberService.getClass ="+ memberService.getClass());*/
    }

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

 

  • 검증하는 부분은 Assertions.asserThat 이용하기 
  • isInstanceOf : memberService가 MemberService.class의 인스턴스 인지 알려준다

 

ApplicationContextBasicfindTest 실행 결과

 

 

우리는 위의 코드에서 빈을 조회할 때 인터페이스(MemverService.class) 를 이용했다. 

하지만 인터페이스가 아닌 구체화된 클래스를 이용해서 빈을 조회할 수 있다

  •  MemberService : 인터페이스  → MemberServiceImpl : 구체화 클래스      

 

@Test
    @DisplayName("구체 타입으로 조회하기")
    void findBeanbyName2(){
        MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
        Assertions.assertThat(memberService).isInstanceOf(MemberServiceImpl.class);

    }

 

하지만 구체화된 클래스로 빈을 조회하는 것은 역할이 아닌 구현에 의존하고 있는 코드 이므로 좋은 코드는 아니다. 

그냥 참고로 인터페이스 뿐만 아니라 구체 클래스로도 조회 가능하다는 것을 알고 있자. 

 

 

 

그런데 스프링 컨테이너에 우리가 찾고자 하는 빈이 없다면 어떤 예외가 발생할까?

 

코드로 알아보자

@Test
    @DisplayName("찾고자하는 빈이 없는 경우")
    void findBeanbyNameX(){
        MemberService memberService = ac.getBean("xxxx", MemberService.class);
        Assertions.assertThat(memberService).isInstanceOf(MemberService.class);
        
    }

 

우리는 스프링 컨테이너에 MemberService.class 타입의 빈은 memberservice만 등록해둔 상황이다.

스프링 컨테이너에는  "xxxx"라는 이름의 MemberService.class 타입의 빈은 존재하지 않는다.

 

따라서 코드를 실행시키면 아래와 같은 오류 문구가 나온다.

 NoSuchBeanDefinitionException: No bean named 'xxxx' available 

 

 

등록되지 않은 빈 이름으로 조회를 하면 NoSuchBeanDefinitionException 예외가 발생한다

 

 

이제 예외가 발생하는 경우를 테스트 코드로 작성해보자.

@Test
    @DisplayName("찾고자하는 빈이 없는 경우")
    void findBeanByNameX() {
        assertThrows( NoSuchBeanDefinitionException.class, () ->
                ac.getBean("xxxx", MemberService.class));
    }

 

  •  assertThows: 특정예외가 발생하는지를 테스트할 때 사용
  • ac.getBean("xxxx", MemberService.class) 를 실행 시켰을 때 NoSuchBeanDefinitionException 예외가 발생하는지 검증하는 코드

 

findByNameX 실행결과

 

 


 

☑️ ApplicationContextBasicFindTest  전체 코드

package hello.core.beanfind;

import hello.core.AppConfig;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ApplicationContextBasicFindTest {

    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("빈 이름으로 조회하기")
    void findBeanbyName(){
        MemberService memberService = ac.getBean("memberService", MemberService.class);
        assertThat(memberService).isInstanceOf(MemberService.class);
        
        /*System.out.println("memberService = " + memberService);
        System.out.println("memberService.getClass = " + memberService.getClass());*/
    }

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

    }

    @Test
    @DisplayName("구체 타입으로 조회하기")
    void findBeanbyName2(){
        MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);

    }

    @Test
    @DisplayName("찾고자하는 빈이 없는 경우")
    void findBeanByNameX() {
        assertThrows(NoSuchBeanDefinitionException.class, () ->
                ac.getBean("xxxxx", MemberService.class));
    }
}