스프링 컨테이너(SpringContainer)
IoC컨테이너라고도 불리며 BeanFactory
와 ApplicationContext
를 통틀어 하는 말입니다. 스프링은 스프링 컨테이너에 의해서 객체를 관리합니다. 이 객체를 저희는 Bean
이라고 합니다. 스프링 컨테이너는 이 Bean
객체를 IoC(제어의 역전)방식으로 관리하고 이 Bean
의 구성정보를 바탕으로 의존관계를 주입해주며, 애플리케이션 구성 및 생애관리를 해줍니다.
빈 팩토리(BeanFactory)
BeanFactory는 스프링 빈을 생성, 의존관계 설정, 사용 등 관리해주는 스프링 컨테이너의 최상위 인터페이스입니다. 이를 구현한 클래스에서는 getBean()
메서드를 통해 오브젝트를 요청할 수 있습니다.
스프링 빈의 이름은 자동으로 클래스명의 가장 첫번째 알파벳만 소문자로 변경되어 저장됩니다.
ex) Apple → apple, Fruit → fruit
애플리케이션 컨텍스트(ApplicationContext)
가장 상위 이미지에서 봤듯이 ApplicaionContext는 BeanFactory를 확장한 인터페이스입니다. 실제 인터페이스에 들어가보면 많은 인터페이스를 상속받아 사용되는것을 확인할 수 있습니다.
위 인터페이스 중 HierachicalBeanFactory
와 ListableBeanFactory
는 저희가 위에서 봤던 BeanFactory
를 상속받은 인터페이스라는 것을 확인할 수 있습니다. 고로 이 두 인터페이스를 구현한 ApplicationContext
또한 BeanFactory
를 상속받았다고 볼 수 있습니다.
애플리케이션 개발 시에는 bean
을 관리하고 조회하는 기능은 물론이고 수 많은 부가기능이 필요합니다. 이 부가기능을 위해 다양한 인터페이스를 상속받은 것입니다. 상속받은 인터페이스들(부가기능)에 대해 간단히 알아보겠습니다.
- EnvironmentCapable
현재 프로그램이 실행중인 환경 정보(Environment)를 가지고 있는 인터페이스입니다. - MessageSource
국제화를 제공하는 인터페이스 입니다. - ApplicationEventPublisher
이벤트를 발행하고 구독하는 모델을 편리하게 지원하는 인터페이스입니다. - ResourcePatternResolver
파일, 클래스패스, 외부 등에서 리소스를 편리하게 조회하기 위한 인터페이스입니다.
ApplicationContext 동작방식
- 설정정보를 가져와서 등록합니다.
@Configuration
애노테이션이 작성된 클래스를 가져온다. - 설정정보를 등록한다.
@Bean
이 작성된 메서드들을 가져와메서드명을 리스트로 관리한다. - getBean()을 통해 오브젝트를 요청하면 2에서 정리해놓은 리스트에 요청된 이름이 있는지 확인합니다.
- 있을 시 빈을 생성하는 메서드를 호출하며
- 생성된 오브젝트를 응답합니다.
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
를 사용하여 가져올 수 있습니다.
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
두 클래스가 반환되는 것을 확인할 수 있습니다.
- 부모 클래스 타입
테스트 결과는 모두 정상 처리되는 것을 확인할 수 있습니다.
정리
오늘은 간단히 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 |