Carefree Hub

Command Palette

Search for a command to run...

Spring Container & Bean - ApplicationContext 와 BeanFactory

Spring Container & Bean - ApplicationContext 와 BeanFactory

스프링 컨테이너의 생성 과정과 스프링 빈 조회 방법 완벽 가이드

Carefreelife98
4분 소요

스프링 컨테이너

기존: 개발자가 직접 자바코드로 모든 것을 함. 스프링 사용: 스프링 컨테이너에 객체를 스프링 빈으로 등록하고, 스프링 컨테이너에서 스프링 빈을 찾아 사용하도록 변경되었다.

Application Context 를 스프링 컨테이너라고 함.

  • 기존에는 AppConfig 등을 사용해서 직접 객체를 생성하고 DI(Dependency Injection)를 함
  • 스프링에서는 구성 정보 설정을 스프링 컨테이너를 통해서 사용
  • 스프링 컨테이너는 @Configuration 이 붙은 구성 클래스를 설정 정보로 사용
    • @Bean 이라 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록
    • 이렇게 스프링 컨테이너에 등록된 객체를 Spring Bean 이라고 함
  • 스프링 빈은 @Bean 이 붙은 메서드의 명을 스프링 빈의 이름으로 사용
  • applicationContext.getBean("빈 이름", 반환 클래스) 를 통해 스프링 빈을 찾을 수 있다

ApplicationContext

  • ApplicationContext 는 Interface 이다.
  • 스프링 컨테이너의 생성 방식 두 가지:
    • XML
    • Annotation 기반의 JAVA 설정 클래스

Annotation 기반의 JAVA 설정 클래스를 통한 생성

java
1ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class)
  • AnnotationConfigApplicationContext() 는 ApplicationContext 인터페이스의 구현체

스프링 컨테이너의 생성 과정

1. 스프링 컨테이너 생성

스프링 컨테이너 생성

  1. new AnnotationConfigApplicationContext(설정/구성 클래스) - 위 구현체 생성 시 스프링 컨테이너가 생성됨
  2. 스프링 컨테이너 내부에는 스프링 빈 저장소가 존재 (Key-Value 형태)
    • Key: 스프링 빈의 이름
    • Value: 스프링 빈 객체
  3. 스프링 컨테이너는 생성 시에 사용한 설정/구성 클래스의 정보를 보고 스프링 빈 등록

2. 스프링 빈 등록

스프링 빈 등록

스프링 컨테이너는 설정 정보 클래스에서 @Bean Annotation이 붙은 메서드들을 모두 찾아 스프링 빈 저장소에 등록한다.

  • Key: 메서드 이름 (옵션 name="" 을 사용해 직접 부여도 가능)
  • 스프링 빈 이름은 유일한 이름을 부여해야 한다
  • Value: 메서드 리턴 값 (객체)

3. 스프링 빈 의존관계 설정

의존관계 설정

  • 스프링 컨테이너는 등록된 설정 정보를 사용해서 의존 관계를 주입한다 (Dependency Injection)
  • 객체 인스턴스 간 의존관계를 동적으로 주입

스프링 빈 조회

모든 빈 출력하기

java
1AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
2
3@Test
4@DisplayName("모든 빈 출력하기")
5void findAllBean() {
6 String[] beanDefinitionNames = ac.getBeanDefinitionNames();
7
8 for (String beanDefinitionName : beanDefinitionNames) {
9 Object bean = ac.getBean(beanDefinitionName);
10 System.out.println("name = " + beanDefinitionName + " Object = " + bean);
11 }
12}

모든 빈 출력

  • ac.getBeanDefinitionNames(): 스프링에 등록된 모든 빈 이름을 조회
  • ac.getBean(): 빈 이름으로 빈 객체(인스턴스)를 조회

애플리케이션 빈 출력하기

java
1@Test
2@DisplayName("애플리케이션 빈 출력하기")
3void findApplicationBean() {
4 String[] beanDefinitionNames = ac.getBeanDefinitionNames();
5
6 for (String beanDefinitionName : beanDefinitionNames) {
7 BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
8
9 if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
10 Object bean = ac.getBean(beanDefinitionName);
11 System.out.println("name = " + beanDefinitionName + " Object = " + bean);
12 }
13 }
14}

애플리케이션 빈 출력

  • ROLE_APPLICATION: 일반적으로 개발자가 개발을 위해 정의한 빈
  • ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈

스프링 빈 조회 (기본)

java
1// 방법 1
2Object bean = ac.getBean(빈 이름, 타입);
3
4// 방법 2
5Object bean = ac.getBean(타입);
6
7// 조회 대상 스프링 빈이 없으면 예외 발생
8// NoSuchBeanDefinitionException: No bean named '~' available

스프링 빈 조회 실패 - NoUniqueBeanDefinitionException

동일한 타입의 빈이 둘 이상 존재할 때 타입으로만 조회하면 예외가 발생한다.

해결 방법: 빈 이름을 지정하여 조회

java
1MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);

특정 타입의 스프링 빈 전체 조회하기

java
1@Test
2@DisplayName("특정 타입을 가진 모든 빈 조회하기")
3void findAllBeanByType() {
4 Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
5 for (String key : beansOfType.keySet()) {
6 System.out.println("key = " + key + " value = " + beansOfType.get(key));
7 }
8
9 assertThat(beansOfType.size()).isEqualTo(2);
10}

특정 타입 빈 조회

BeanFactory

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

ApplicationContext

  • BeanFactory 기능을 모두 상속받아서 제공
  • 애플리케이션 개발 시 빈 관리/조회 기능 외에 추가적인 부가 기능 제공

ApplicationContext 가 제공하는 부가기능

ApplicationContext 부가기능

  • 메시지 소스를 활용한 국제화 기능: 한국에서 접근 시 한국어, 영미권에서 접근 시 영어 출력
  • 환경 변수: Local, Dev, Release 등의 환경을 구분하여 처리
  • Application Event: 이벤트를 발행하고 구독하는 모델을 편리하게 지원
  • 편리한 리소스 조회: File, Classpath, External 등의 Resource 들을 편리하게 조회

정리

  • ApplicationContext는 BeanFactory의 기능을 상속받는다
  • ApplicationContext는 빈 관리기능 + 편리한 부가 기능을 제공한다
  • BeanFactory를 직접 사용할 일은 거의 없다
  • BeanFactory / ApplicationContext를 스프링 컨테이너라 한다

참고: Inflearn - 김영한님 강의(스프링 핵심 원리 기본편)