(인프런) 김영한님의 스프링 핵심 원리-기본편을 공부하고 리뷰한 글입니다.
1. 스프링 컨테이너 생성
● ApplicationContext = 스프링 컨테이너
<스프링 컨테이너 생성 방법>
1) XML 기반으로 생성
2) 애노테이션 기반의 자바 설정 클래스로 생성
- AppConfig를 사용한 방식 -> 주로 사용하는 방식
// 스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
- ApplicaionContext = 인터페이스
- AnnotationConfigApplicaionContext 클래스 = ApplicationContext 인터페이스의 구현체
(참고) 스프링 컨테이너는 1) BeanFactory, 2) ApplicationContext 로 구분된다.
BeanFactory를 직접 사용하는 경우는 거의 없으므로 일반적으로 ApplicationContext를 스프링 컨테이라 한다. (자세한건 뒤에서 설명)
1. 스프링 컨테이너의 생성과정
1) 스프링 컨테이너 생성
new AnnotationConfigApplicationContext(AppConfig.class)
스프링 컨테이너를 생성할 때는 구성 정보를 파라미터 값으로 넘겨주어야 한다. (여기서는 AppConfig.class = 구성 정보)
2) 스프링 빈 등록
스프링 컨테이너는 파라미터로 넘어온 설정 클래스 정보를 사용해 스프링 빈을 등록한다.
<스프링 빈 이름>
1) 메서드 이름 사용(default)
2) 직접 부여
- @Bean(name="memberService2")
(주의) 빈 이름은 항상 다른 이름을 부여해야 한다! 같은 이름을 부여하면 다른 빈이 무시되거나 기존 빈을 덮어쓰는 등 설정에 따라 오류가 발생한다.
3) 스프링 빈 의존관계 설정 - 준비
4) 스프링 빈 의존관계 설정 - 완료
스프링 컨테이너는 설정 정보를 참고해서 의존 관계를 주입(DI) 한다.
(단순히 자바 코드를 호출하는 것 같지만 차이가 있음. 뒤에 싱글톤 컨테이너에서 설명 예정)
(참고)
스프링은 빈을 생성하고, 의존관계를 주입하는 단계가 나누어져 있다. 그런데 이렇게 자바 코드로 스프링 빈을 등록하면 생성자를 호출하면서 의존관계 주입도 한번에 처리된다. 여기서는 이해를 돕기 위해 개념적으로 나누어 설명했다. 자세한 내용은 의존관계 자동 주입에서 다시 설명하겠다.
<정리>
1) 스프링 컨테이너 생성
2) 설정(구성) 정보를 참고해서 스프링 빈 등록
3) 의존관계 설정
2. 컨테이너에 등록된 모든 빈 조회
스프링 컨테이너에 위에서 등록한 스프링 빈들이 잘 등록되었는지 확인해본다.
1. ApplicationContextInfoTest
package hello.core.beanfind;
import hello.core.AppConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("모든 빈 출력하기")
void findAllBean() {
// 스프링 컨테이너에 등록된 모든 빈의 이름 조회
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
// 빈 이름(key)로 빈(value) 얻기
Object bean = ac.getBean(beanDefinitionName);
System.out.println("bean = " + beanDefinitionName + " object = " + bean);
}
}
@Test
@DisplayName("애플리케이션 빈 출력하기")
void findApplicationBean() {
// 스프링 컨테이너에 등록된 모든 빈의 이름 조회
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
// 빈에 대한 메타데이터 정보
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
// ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
// ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
// 빈 이름(key)로 빈(value) 얻기
Object bean = ac.getBean(beanDefinitionName);
System.out.println("bean = " + beanDefinitionName + " object = " + bean);
}
}
}
}
- 클래스나 메서드 앞에 public 을 명시하지않아도 자동으로 public 처리됨
2. 모든 빈 출력하기
스프링에 등록된 모든 빈을 출력한다.
● ac.getBeanDefinitionNames(): 스프링에 등록된 모든 빈 이름을 조회
● ac.getBean(빈이름): 빈 이름으로 빈 객체(인스턴스) 조회
1) 스프링 내부에서 기본으로 생성된 빈
2) AppConfig 정보를 통해 등록한 스프링 빈
3. 애플리케이션 빈 출력하기
스프링 내부에서 사용하는 빈은 제외하고 내가 등록한 빈만 출력한다.
● ac.getBeanDefinition(빈 이름): 빈 이름으로 빈의 메타데이터 조회
● beanDefinition.getRole(): 빈 구분하기
- ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
- ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
1) AppConfig 정보를 통해 등록한 스프링 빈