[Spring] 스프링 컨테이너

UiJu Hong / 홍의주·2024년 4월 21일

스프링

목록 보기
2/2

스프링 컨테이너(Spring Container)

스프링 컨테이너는 자바 객체, 빈(Bean)의 생명 주기를 관리하며, 생성된 빈에게 추가적인 기능을 제공하는 것이다.

✏️ 스프링 컨테이너 생성

AppConfig.class

@Configuration
public class AppConfig {
    @Bean
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }
    
    @Bean
    public OrderService orderService(){
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    //중복을 방지하고, 역할과 구현 클래를 한 눈에 구분할 수 있다.
    @Bean
    public  MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    
    @Bean
    public DiscountPolicy discountPolicy() {
        //return new FixDiscountPolicy();
        
        //할인 정책이 바뀌었다.
        return new RateDiscountPolicy();
    }
}

  • 그림과 같이 빈 이름은 메서드 이름을 사용한다.
  • @Bean(name="myBean") 과 같이 빈 이름을 직접 부여할 수도 있지만, 빈 이름은 항상 다른 이름을 부여해야 한다.

✏️ 스프링 빈 조회

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

ApplicationContext applicationContext =
                     new AnnotationConfigApplicationContext(AppConfig.class);
  • ApplicationContext 인터페이스를 스프링 컨테이너라 하며 AnnotationConfigApplicationContext는 스프링 컨테이너 인터페이스의 구현체이다.

BeanFactory는 스프링 컨테이너의 최상위 인터페이스로 빈을 관리하고 조회하는 역할을 담당하며 getBean() 을 제공한다.

  • ApplicationContext는 기능을 상속받아 빈 관리기능 + 편리한 부가 기능을 제공한다. 모두 스프링 컨테이너라 한다.
  • ApplicationContext가 제공하는 부가기능에는 메시지소스를 이용한 국제화 기능, 환경변수, 이벤트, 리소스 조회가 있다.

스프링 빈을 찾는 기본적인 조회 방법으로 다음과 같이 있다.

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

이를 활용하여 빈을 조회하는 테스트 코드를 작성하였다.

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);
    }
    @Test
    @DisplayName("이름 없이 타입으로만 조회")
    void findBeanByType(){
        MemberService memberService = ac.getBean(MemberService.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }
    @Test
    @DisplayName("구체 타입으로 조회")
    void findBeanByName2(){
        // 구현체로 확인하면 유연성이 떨어지지만 필요한 경우도 있음
        MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }

    @Test
    @DisplayName("빈 이름으로 조회X")
    void findBeanByNameX(){
        //MemberService memberService = ac.getBean("xxxxx", MemberServiceImpl.class);
        // ()-> 뒤의 로직 실행시, 다음과 같은 Exception 발생하는지에 대한 확인
        assertThrows(NoSuchBeanDefinitionException.class,
                        () -> ac.getBean("xxxxx", MemberServiceImpl.class));
    }
}

마지막 테스트는 조회 빈이 없는 경우 NoSuchBeanDefinitionException 예외 발생을 확인한 것이다.



이 게시물은 인프런 김영한 강사의 스프링 핵심 원리 - 기본편 을 듣고 작성하였습니다.

0개의 댓글