스프링 컨테이너와 스프링 빈

Sangkyeong Lee·2021년 5월 19일

인프런 강의 < 스프링 핵심 원리 - 기본편 > 정리


스프링 컨테이너 생성

    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  • ApplicationContext를 스프링 컨테이너라고 한다
  • ApplicationContext는 인터페이스다.
  • XML 기반과 에노테이션 기반이 존재한다

스프링 컨테이너 생성과정

  • 스프링 컨테이너 생성
  • 스프링 컨테이너에 AppConfig.class 정보를 넘긴다

  • 스프링 빈 등록
  • 스프링 컨테이너는 파라미터로 넘어온 클래스 정보를 보고 스프링 빈으로 등록한다.
  • 빈 이름은 메서드 이름을 사용
  • 빈 이름은 항상 다른 이름으로 부여

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

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

    설정 정보를 참조해서 의존관계를 주입한다.

스프링 빈 조회

컨테이너에 등록된 모든 빈 조회

class ApplicationContextInfoTest {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("모든 빈 출력하기")
    void findAllBean() {
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            Object bean = ac.getBean(beanDefinitionName);
            System.out.println("name=" + beanDefinitionName + " object=" + bean);
        }
    }

    @Test
    @DisplayName("애플리케이션 빈 출력하기")
    void findApplicationBean() {
        String[] beanDefinitionNames = ac.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
            //Role ROLE_APPLICATION: 직접 등록한 애플리케이션 빈
            //Role ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈
            if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
                Object bean = ac.getBean(beanDefinitionName);
                System.out.println("name=" + beanDefinitionName + " object=" + bean);
            }
        }
    }
}

모든 빈 출력하기

  • 실행하면 스프링에 등록된 모든 빈 정보를 출력할 수 있다.
  • ac.getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름을 조회한다.
  • ac.getBean() : 빈 이름으로 빈 객체(인스턴스)를 조회한다.

애플리케이션 빈 출력하기

  • 스프링이 내부에서 사용하는 빈은 getRole() 로 구분할 수 있다.
  • ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
  • ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

가장 기본 적인 조회 방법

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

  • ac.getBean(타입)

  • 조회 시 빈이 등록되어있지 않다면
    NoSuchBeanDefinitionException: No bean named 'xxxxx' available의 예외가 발생한다.

동일한 타입이 둘 이상 있을 때

  • 타입으로 조회할 때, 타입이 중복되면 오류가 발생하므로 빈 이름을 지정
  • ac.getBeansOfType() 로 모든 해당 타입의 빈 조회
class ApplicationContextSameBeanFindTest {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);

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

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

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

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

상속관계

  • 부모 타입으로 조회하면, 자식 타입도 다같이 조회된다.
  • Object로 조회하면 모든 빈이 조회된다.

BeanFactory와 ApplicationContext

BeanFactory

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

ApplicationContext

  • BeanFactory 기능을 모두 상속받아 제공
  • 부가기능이 더 많음

스프링 빈 설정 메타 정보 - BeanDefinition

  • BeanDefinition = 추상화

  • 역할과 구현을 개념적으로 나눈 것 이라고 이해 하면 된다.

  • XML인지 자바 코드인지 몰라도 되고, BeanDefinition만 알면 된다.

  • 다음에 추가적으로 공부해보기


< 자료 출처: 스프링 핵심 원리 - 기본편 >

profile
💻Backend Developer

0개의 댓글