[스프링] SpringContainer, BeanFactory, ApplicationContext

2024. 5. 21. 15:38·BackEnd/Spring

스프링 컨테이너(SpringContainer)

IoC컨테이너라고도 불리며 BeanFactory와 ApplicationContext를 통틀어 하는 말입니다. 스프링은 스프링 컨테이너에 의해서 객체를 관리합니다. 이 객체를 저희는 Bean 이라고 합니다. 스프링 컨테이너는 이 Bean 객체를 IoC(제어의 역전)방식으로 관리하고 이 Bean 의 구성정보를 바탕으로 의존관계를 주입해주며, 애플리케이션 구성 및 생애관리를 해줍니다.

image

 

 

빈 팩토리(BeanFactory)

BeanFactory는 스프링 빈을 생성, 의존관계 설정, 사용 등 관리해주는 스프링 컨테이너의 최상위 인터페이스입니다. 이를 구현한 클래스에서는 getBean() 메서드를 통해 오브젝트를 요청할 수 있습니다.

스프링 빈의 이름은 자동으로 클래스명의 가장 첫번째 알파벳만 소문자로 변경되어 저장됩니다.
ex) Apple → apple, Fruit → fruit

BeanFactory

 

 

애플리케이션 컨텍스트(ApplicationContext)

가장 상위 이미지에서 봤듯이 ApplicaionContext는 BeanFactory를 확장한 인터페이스입니다. 실제 인터페이스에 들어가보면 많은 인터페이스를 상속받아 사용되는것을 확인할 수 있습니다.

ApplicationContext

위 인터페이스 중 HierachicalBeanFactory 와 ListableBeanFactory 는 저희가 위에서 봤던 BeanFactory 를 상속받은 인터페이스라는 것을 확인할 수 있습니다. 고로 이 두 인터페이스를 구현한 ApplicationContext 또한 BeanFactory를 상속받았다고 볼 수 있습니다.

imageimage

애플리케이션 개발 시에는 bean을 관리하고 조회하는 기능은 물론이고 수 많은 부가기능이 필요합니다. 이 부가기능을 위해 다양한 인터페이스를 상속받은 것입니다. 상속받은 인터페이스들(부가기능)에 대해 간단히 알아보겠습니다.

  • EnvironmentCapable
    현재 프로그램이 실행중인 환경 정보(Environment)를 가지고 있는 인터페이스입니다.
  • MessageSource
    국제화를 제공하는 인터페이스 입니다.
  • ApplicationEventPublisher
    이벤트를 발행하고 구독하는 모델을 편리하게 지원하는 인터페이스입니다.
  • ResourcePatternResolver
    파일, 클래스패스, 외부 등에서 리소스를 편리하게 조회하기 위한 인터페이스입니다.

ApplicationContext 동작방식

  1. 설정정보를 가져와서 등록합니다.
    @Configuration 애노테이션이 작성된 클래스를 가져온다.
  2. 설정정보를 등록한다.
    @Bean 이 작성된 메서드들을 가져와메서드명을 리스트로 관리한다.
  3. getBean()을 통해 오브젝트를 요청하면 2에서 정리해놓은 리스트에 요청된 이름이 있는지 확인합니다.
  4. 있을 시 빈을 생성하는 메서드를 호출하며
  5. 생성된 오브젝트를 응답합니다.

 

 

Application의 getBean() 메서드를 사용해보자.

Spring BeanFactory는 설정정보를 바탕으로 오브젝트를 생성하고 관계를 맺어줍니다. 설정정보를 생성하는 방식은 XML방식과 Annotation방식이 있는데 그 중 Annotation방식을 사용해서 테스트 해보겠습니다.
이번 테스트는 단일 오브젝트를 가져오는 getBean()과 동일 타입에 해당하는 여러 오브젝트를 가져오는 getBeans() 두 메서드를 사용해볼 것입니다.
한번에 테스트를 해보기 위해 Fruit라는 인터페이스를 선언한 후 이 인터페이스를 상속받은 과일 클래스를 두개 구현한 후 테스트 하겠습니다. 코드는 아래와 같습니다.

1. 객체 생성

Fruit 인터페이스

public interface Fruit {
    String getName();
}

Fruit를 구현한 Apple 클래스

public class Apple implements Fruit {

    private static final String name = "Apple";

    @Override
    public String getName() {
        return name;
    }
}

Fruit를 구현한 Melon 클래스

public class Melon implements Fruit {
    private static final String name = "Melon";

    @Override
    public String getName() {
        return name;
    }
}

2. 설정 클래스

구현한 클래스를 스프링빈으로 등록하기 위해 설정파일을 작성할 것입니다. 설정파일은 애노테이션 방식을 사용하기로 했으므로 설정 클래스에 @Configuration 을 작성해주겠습니다. @Configuration 은 해당 클래스가 빈 팩토리를 위해 오브젝트 설정을 담당하는 클래스라고 명시하는 것입니다. 즉, 빈 정의를 포함하고 있는 클래스라고 명시한다고 보면 됩니다.

@Configuration이 작성된 클래스의 내부에 오브젝트를 반환하는 메서드를 작성합니다. 메서드 위에 @Bean 을 작성하여 이 오브젝트를 빈으로 등록하겠다고 명시합니다.

@Configuration
public class FruitAppConfig {

    @Bean
    public Apple apple() {
        return new Apple();
    }

    @Bean
    public Melon melon() {
        return new Melon();
    }
}

3. 테스트 클래스

설정파일까지 작성했다면 해당 코드가 잘 동작하는지 확인하는 테스트코드를 작성해보겠습니다.

저희는 Annotation을 사용하여 설정정보를 작성했습니다. 이처럼 Annotation을 사용해 작성한 설정정보는 ApplicatonContext를 구현한 AnnotationConfigApplicationContext를 사용하여 가져올 수 있습니다.

image

AnnotationConfigApplicationContext를 생성하면서 위에서 작성했던 컴포넌트 클래스 FruitAppConfig.class를 인자로 넘겨주어 설정정보를 받아옵니다.

getBean()과 getBeans()는 ApplicationContext 인터페이스에 정의된 메서드이므로 상위 클래스로 받아와서 사용할 수 있습니다.

public class FruitAppConfigTest {

    @Test
    void getBeanTest() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(FruitAppConfig.class);

        Apple apple = ac.getBean("apple", Apple.class);
        Melon melon = ac.getBean("melon", Melon.class);

        assertThat(apple).isInstanceOf(Apple.class);
        assertThat(melon).isInstanceOf(Melon.class);
    }

    @Test
    void getBeansTest() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(FruitAppConfig.class);
        Map<String, Fruit> beans = ac.getBeansOfType(Fruit.class);

        System.out.println("beans = " + beans);

        assertThat(beans.size()).isEqualTo(2);
    }
}
  • getBean()
    • 각각 클래스의 빈이름과 타입을 인자로 넘겨주면 해당 빈이름에 맞는 오브젝트를 반환합니다.
    • 받아온 오브젝트가 해당 객체의 타입이 맞는지 Assertion을 사용해 확인하면 정상적으로 처리되는 것을 확인할 수 있습니다.
  • getBeans()
    • 부모 클래스 타입 Fruit.class 를 인자로 넘겨 타입에 해당하는 빈을 맵으로 가져옵니다.
    • 맵은 <빈 이름, 생성된 오브젝트> 구성으로 반환됩니다.
    • 간단히 프린트해보면 위에서 정의한 Apple 과 Melon 두 클래스가 반환되는 것을 확인할 수 있습니다.
      image

테스트 결과는 모두 정상 처리되는 것을 확인할 수 있습니다.

image

 

 

정리

오늘은 간단히 SpringContainer 대해서 알아보았습니다.

  • BeanFactory와 ApplicationContext를 통틀어서 SpringContainer라고 한다.
  • BeanFactory는 스프링 빈의 생애주기를 관리한다.
  • 애플리케이션을 개발하다보면 빈의 생애주기 뿐만 아니라 부수기능이 필요해진다. (리소스 조회, 환경 설정 조회, 국제화, 이벤트 발행 및 구독 등)
  • 이러한 부수기능을 포함하여 BeanFactory를 확장한 것이 ApplicationContext이다.
  • 빈 등록 방법에는 XML과 Annotation 방식이 있다.
  • 스프링 컨텍스트에 등록된 빈은 getBean() 메서드를 통해 가져올 수 있다.

'BackEnd > Spring' 카테고리의 다른 글

[Spring] 빈 스코프(BeanScope)  (0) 2024.06.17
컴포넌트 스캔(@ComponentScan)에 대해 알아보자  (0) 2024.06.04
싱글톤 컨테이너(Singleton Container)란 무엇인가  (0) 2024.06.03
'BackEnd/Spring' 카테고리의 다른 글
  • [Spring] 빈 스코프(BeanScope)
  • 컴포넌트 스캔(@ComponentScan)에 대해 알아보자
  • 싱글톤 컨테이너(Singleton Container)란 무엇인가
hwa2
hwa2
  • hwa2
    나도! 기억하고싶었어!
    hwa2
  • 전체
    오늘
    어제
    • 분류 전체보기 (27)
      • 공부 (4)
        • 네트워크 (2)
        • 알고리즘 (2)
        • 자료구조 (0)
      • 디자인패턴 (1)
      • DevOps (1)
        • 데이터베이스 (1)
      • BackEnd (11)
        • JAVA (7)
        • Spring (4)
      • FrontEnd (6)
        • Javascript (6)
      • 코딩테스트 풀어보자! (1)
      • 해결해보자. (1)
      • 플젝..해보자.. (2)
      • 우테코 7기 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    회고
    멋쟁이사자처럼후기
    readline
    자바스크립트
    싱글톤컨테이너
    프리코스
    FunctionalInterface
    node.js
    싱글톤패턴
    jdk8
    스레드 동기화
    TemplateMethodPattern
    우테코7기
    nodejs
    Java
    JS
    함수형인터페이스
    우테코
    우테코 7기
    JavaScript
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
hwa2
[스프링] SpringContainer, BeanFactory, ApplicationContext
상단으로

티스토리툴바