- 스프링으로 전환
- 이전 포스팅에서 순수 자바코드로 DI 컨테이너(AppConfig)를 만들어봤다.
- 이제 본격적으로 AppConfig를 스프링 환경으로 바꿔보자. 스프링 환경으로 구성했을 때의 이점은 하나씩 추가될 것이다.
* 이전포스팅 : https://dong-woo.tistory.com/63
[Spring] 순수 자바코드를 통해 회원관리, 주문서비스를 만들고 객체지향원리 적용하기
- 객체지향원리? 간단한 회원관리서비스, 주문서비스(할인정책)을 순수 자바코드로 만들어보며 좋은 객체지향 설계원칙 5가지(SOLID)를 지킬 수 있는지 단계별로 확인해보자. 본 포스팅을 이해하
dong-woo.tistory.com
- 스프링 컨테이너? 스프링 빈?
- 스프링에서는 기존 AppConfig같은 설정정보 파일을 입력으로 받아 자체 컨테이너에서 관리하는 기능을 제공한다.
- 스프링 컨테이너를 생성하는 방법은 다음과 같다
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
- ApplicationContext는 인터페이스고, 인터페이스의 구현체로 어노테이션 자바 설정 기반, XML기반으로 만들 수 있는데 현재 AppConfig는 어노테이션 자바 설정 기반이므로 AnnotationConfigApplicationContext를 구현체로 생성한다.
- 여기서 ApplicationContext를 스프링 컨테이너 라고 부른다.
- 기존의 AppConfig안에 메소드를 만들어서 역할을 호출했을 때 구현체를 반환해줬는데, 이러한 모든 메소드에 @Bean을 붙여줄 수 있다. 메소드 하나하나를 스프링 빈으로 등록하겠다는 의미다.
- 메소드명이 스프링 빈 이름으로 등록되고, 반환값이 스프링 빈의 객체로 등록된다, 아래 그림을 보면 이해가 될 것이다.
- 중요한 점은 스프링 컨테이너에서는 먼저 스프링 빈 등록을 마치고, 이후 의존관계 주입이 발생한다.
하지만 지금처럼 스프링 빈을 등록하려는데, 생성자를 호출함으로 인해 스프링 빈이 등록됨과 동시에 의존관계 주입이 일어나는 상황도 존재한다.
- 스프링 빈을 조회하는 방법
- 자, 이제 등록한 빈들을 다양한 방식으로 조회해보자
public 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);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println(" name = " + beanDefinitionName + ", object = " + bean);
}
}
@Test
@DisplayName("모든 빈 조회")
void findAllByObject() {
Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + ", value = " + beansOfType.get(key));
}
}
}
- ac.getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름을 조회한다. (배열에 담음)
- ac.getBean() : 빈 이름으로 빈 객체 '하나' 를 조회한다. getBean()을 사용할 때에는 2가지로 사용할 수 있다.
1. ac.getBean(빈이름, 타입)
2. ac. getBean(타입)
타입으로 조회했을 시 중복타입이 존재한다면 예외가 발생한다. 이럴 경우 빈 이름까지 지정해주면 된다. - ac.getBeansOfType() : 타입으로 조회시 같은 타입의 스프링 빈이 둘 이상이면 오류가 발생한다. 모든 빈을 조회하고싶으면 이 메소드를 사용하면 된다. Map 자료형으로 모든 빈이 저장된다.
- 부모타입으로 조회시 자식타입이 다 딸려온다. 그래서 모든 자바 객체의 최고 부모인 'Object' 타입으로 조회하면, 모든 스프링 빈을 조회한다.
- 스프링이 내부에서 사용하는 빈은 제외하고, 내가 등록한 빈만 출력하고 싶다면 getRole()을 통해 구분할 수 있다.
1. ROLE_APPLICATION : 사용자가 정의한 빈
2. ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
- BeanFactory <-> ApplicationContext
- ApplicationContext가 스프링 컨테이너라고 언급했지만, 사실 스프링 컨테이너는 BeanFactory와 ApplicationContext 두 가지가 있다고 말할 수 있다.
- 사진처럼 BeanFactory가 최상위 인터페이스로 자리하고있다.
- 빈 팩토리는 getBean()을 제공하고, 스프링 빈을 관리하고 조회하는 역할을 담당한다.
- ApplicationContext는 빈 팩토리를 상속받아 해당 인터페이스의 모든 기능을 제공하고, 추가로 수 많은 부가기능을 제공한다.
- 애플리케이션을 개발할 때에는 빈을 관리하고 조회하는 기능은 물론, 수 많은 부가기능이 필요하기 때문에, 주로 스프링 컨테이너를 ApplicationContext로 생성한다. (BeanFactory를 직접 사용할 일은 거의 없다.)
- 무슨 부가기능을 제공할까? 아래 사진을 통해 확인하자.
- 이러한 다양한 기능을 제공받을 수 있기 때문에, 스프링 컨테이너를 사용한다고 생각하면 된다. 수많은 기능이 더 소개될 것이다.
- BeanDefinition
- AppConfig와 같은 설정 정보 파일의 형식을 어노테이션 자바 설정 파일로도 할 수 있고, XML 파일로도 가능하다고 했다.
- 스프링은 어떻게 이런 다양한 설정 형식을 지원할까?
- 바로 BeanDefinition이라는 '추상화' 가 있다.
- 쉽게 말해, 역할과 구현을 나눈것이다.
- XML을 읽어서 BeanDefinition을 만든다.
- 자바 코드를 읽어서 BeanDefinition을 만든다.
- 스프링 컨테이너는 자바코드인지 XML인지 무슨파일인지 몰라도 된다! 오직 BeanDefinition만으로 어떤 구성인지 파악한다.
- BeanDefinition을 빈 설정 메타정보라고 한다. @Bean, <bean> 하나당 메타 정보가 하나씩 생성된다
- 정리
- 기존의 순수 자바환경의 DI컨테이너를 스프링 컨테이너 환경으로 전환했다.
- 다음 포스팅 부터는 스프링 컨테이너 환경에서 제공하는 기능들을 하나씩 알아보자.
출처 : 인프런, 김영한의 스프링 핵심 원리 - 기본편
'Spring' 카테고리의 다른 글
[Spring] 의존관계 자동주입, @Autowired (1) | 2023.07.02 |
---|---|
[Spring] 컴포넌트 스캔, @ComponentScan (0) | 2023.06.26 |
[Spring] 싱글톤 패턴, 싱글톤 컨테이너 (0) | 2023.06.26 |
[Spring] 순수 자바코드를 통해 회원관리, 주문서비스를 만들고 객체지향원리 적용하기 (0) | 2023.06.23 |
[Spring] 객체지향설계(SOLID)와 스프링 (1) | 2023.06.19 |