거누의 개발노트
[Spring] 스프링 컨테이너와 빈 본문
스프링 컨테이너와 빈
스프링 컨테이너는 자바 객체의 생명 주기를 관리하며, 생성된 자바 객체들에게 추가적인 기능을 제공하는 역할을 한다.
여기서 말하는 자바 객체를 스프링에서는 빈(Bean)이라고 부른다.
저번에 공부했던 IoC와 DI의 원리가 이 스프링 컨테이너에 적용된다.
개발자는 new 연산자, 인터페이스 호출, 팩토리 호출 방식으로 객체를 생성하고 소멸시킬 수 있는데, 스프링 컨테이너가 이 역할을 대신해 준다.
스프링 컨테이너의 종류
BeanFactory
BeanFactory는 빈을 등록하고 생성하고 조회하고 돌려주는 등 빈을 관리하는 역할을 한다.
빈을 추가할 때는 이런식으로 추가합니다.
@Configuration
public class AppConfig {
@Bean
public OrderService orderService() {
return new OrderServiceImpl(discountPolicy());
}
@Bean
public FixDiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
스프링 컨테이너 안에 스프링 빈 저장소가 있고 위 그림처럼 빈이 저장된다고 생각하면 이해가 쉽다.
이제 컨테이너 안에 들어가 있는 빈을 사용해보자
public class Main {
public static void main(String[] args) {
final BeanFactory beanFactory = new AnnotationConfigApplicationContext(AppConfig.class);
final OrderService orderService = beanFactory.getBean("orderService", OrderService.class);
final Order order = orderService.createOrder(15, "샤프", 3000);
System.out.println(order.getDiscountPrice());
}
}
BeanFactory를 AnnotationConfigApplicationContext로 구현하고, AppConfig를 구성정보로 지정한다.
그리고 빈 저장소에서 orderService를 가져올건데 OrderService 타입을 지정해주지 않으면 Object 타입으로 오니 주의해야한다고 한다.
.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4e718207
13:52:20.460 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
13:52:20.738 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
13:52:20.741 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
13:52:20.743 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
13:52:20.745 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
13:52:20.758 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
13:52:20.767 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService'
13:52:20.793 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'discountPolicy'
1000
위 코드를 실행하면 이런 로그가 발생한다.
뭔가 긴 빈 이름은 미리 정의된 초기 빈들이고 appConfig, orderService, discountPolicy가 우리가 등록한 빈이라는 사실을 알 수 있다. 또한, OrderService는 DiscountPolicy를 주입해 주어야 하는데 스프링 컨테이너가 알아서 주입을 해 줍니다.
ApplicationContext
ApplicationContext도 BeanFactory처럼 빈을 관리할 수 있습니다. Main 코드에서 BeanFactory를 ApplicationContext로만 바꾸고 실행해 보면,
public class Main {
public static void main(String[] args) {
final ApplicationContext beanFactory = new AnnotationConfigApplicationContext(AppConfig.class);
final OrderService orderService = beanFactory.getBean("orderService", OrderService.class);
final Order order = orderService.createOrder(15, "샤프", 3000);
System.out.println(order.getDiscountPrice());
}
}
동일한 결과를 얻을 수 있다.
13:56:08.105 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@4e718207
13:56:08.136 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
13:56:08.391 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
13:56:08.396 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
13:56:08.398 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
13:56:08.401 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
13:56:08.417 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'appConfig'
13:56:08.431 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderService'
13:56:08.458 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'discountPolicy'
1000
이 이유는 ApplicationContext가 BeanFactory의 상속을 받았기 때문이다.
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
...
}
완전 정확히 BeanFactory 자체에 상속을 받은 것은 아니지만 빈을 관리하는 기능을 물려받은 것이다.
그리고 ApplicationContext는 그 외에도 국제화가 지원되는 텍스트 메시지 관리, 이미지같은 파일 자원을 로드, 리너스로 등록된 빈에게 이벤트 발생 알림 등 부가적인 기능을 가지고 있다.
그래서 스프링 컨테이너하면 주로 이 ApplicationContext를 뜻한다고 한다.
또한, 빈 관리라는 기능도 두 컨테이너가 동일한 기능을 하지는 않는다.
BeanFactory는 처음으로 getBean() 메소드가 호출된 시점에서야 해당 빈을 생성하고,
ApplicationContext는 Context 초기화 시점에 모든 싱글톤 빈을 미리 로드한 후 애플리케이션 가동 후에는 빈을 지연 없이 받을 수 있다.
22-06-09 싱글톤 컨테이너에 대해 정리하기
'Spring' 카테고리의 다른 글
Spring Boot OAuth2.0 적용기 (0) | 2022.07.04 |
---|---|
Spring Boot - Github Action, S3, EC2, CodeDeploy 연동 (0) | 2022.06.23 |
[Spring] DI(Dependency Injection)를 사용하는 이유 (1) | 2022.06.07 |
Controller, Service, Repository (0) | 2022.06.07 |
[Spring] Spring Data JPA 기본 사용법 ( JpaRepository ) (1) | 2022.06.05 |