03. Spring Basic - 스프링 컨테이너와 빈

MoonJaeGyeong·2023년 8월 26일

Spring

목록 보기
3/10
post-thumbnail

1. 스프링 컨테이너(Spring Container)


스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트이다.
스프링 컨테이너는 자바 객체의 생명 주기를 관리하며, 생성된 자바 객체들에게 추가적인 기능을 제공한다.

즉, 스프링 컨테이너는 내부에 존재하는 빈의 생명주기를 관리(빈의 생성, 관리, 제거 등) 하며, 생성된 빈에게 추가적인 기능을 제공하는 것이다

1.1 스프링 컨테이너

// 스프링 컨테이너 생성
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
  • ApplicationContext, BeanFactory 를 스프링 컨테이너라 한다.
  • 스프링 컨테이너는 XML을 기반, 애노테이션 기반의 자바 설정 클래스로 만들 수 있다.

BeanFactory 와 ApplicationContext에 대해서 알아보자.
컨테이너 상속 관계

BeanFactory

  • 스프링 컨테이너의 최상위 인터페이스다.
  • 스프링 빈을 관리하고 조회하는 역할을 담당
  • getBean() 을 제공한다.
  • 지금까지 우리가 사용했던 대부분의 기능은 BeanFactory 가 제공하는 기능이다.

ApplicationContext

  • BeanFactory 기능을 모두 상속받아서 제공한다.
  • 애플리케이션을 개발할 때 부가기능 제공

ApplicationContext가 제공하는 부가기능
ApplicatinoContext 부가기능 상속

메세지소스를 활용한 국제화 기능

  • 위치기반으로 접속 나라의 언어로 출력

환경변수

  • 로컬, 개발, 운영등을 구분해서 처리

애플리케이션 이벤트

  • 이벤트를 발행하고 구독하는 모델을 편리하게 지원

편리한 리소스 조회

  • 파일, 클래스패스, 외부 등에서 리소스를 편리하게 조회

1.2 스프링 컨테이너 생성

1. 스프링 컨테이너 생성

컨테이너 생성

  • new AnnotationConfigApplicationContext(AppConfig.class)
  • 스프링 컨테이너 생성 시 구성 정보를 지정해야 한다. -> (AppConfig.class)

2. 스프링 빈 등록

스프링 빈 등록

  • 빈 이름은 메서드 이름을 사용하나 직접 부여할 수 도 있다
  • @Bean(name="memberServiceOne")

주의사항 : Bean 이름은 항상 다른 이름을 부여해야 한다.

3. 스프링 빈 의존관계 설정

스프링 빈 DI

  • 스프링 컨테이너는 설정 정보를 참고해서 의존관계 주입(DI)

2. 스프링 빈 조회


  • ac.getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름 조회
  • ac.getBean(Type), ac.getBean("Bean_Name", Type) : 빈 이름 과 타입으로 빈 인스턴스를 조회한다.
  • 조회 대상이 없을 시 예외 발생 NoSuchBeanDefinitionException: No bean named 'xxxxx' available
  • 스프링 내부에서 사용하는 빈은 getRole()로 구분 할 수 있다.
    ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
    ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

2.1 스프링 빈 조회 - 기본

빈 이름으로 조회

void findBeanByName() {
 	MemberService memberService = ac.getBean("memberService", 
	MemberService.class);
 	assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
 }

이름 없이 타입만으로 조회

void findBeanByType() {
 	MemberService memberService = ac.getBean(MemberService.class);
 	assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
 }

구체 타입으로 조회

void findBeanByName2() { 
	MemberServiceImpl memberService = 	ac.getBean("memberService", 
	MemberServiceImpl.class);
 	assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
 }

빈 이름으로 조회X

void findBeanByNameX() {
 	Assertions.assertThrows(NoSuchBeanDefinitionException.class, () ->
	ac.getBean("xxxxx", MemberService.class));
	 }
}

참고 : 구체 타입으로 조회하면 변경시 유연성이 저하된다.

2.2 스프링 빈 조회 - 타입 중복

타입으로 조회시 타입이 중복되면 오류 발생 하므로 빈 이름을 지정

void findBeanByName() {
 	MemberRepository memberRepository = ac.getBean("memberRepository1", 
	MemberRepository.class);
 	assertThat(memberRepository).isInstanceOf(MemberRepository.class);
 }

특정 타입을 모두 조회

void findAllBeanByType() {
 	Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
	 for (String key : beansOfType.keySet()) {
 		System.out.println("key = " + key + " value = " + beansOfType.get(key));
 	}
 	System.out.println("beansOfType = " + beansOfType);
    assertThat(beansOfType.size()).isEqualTo(2);
 }

2.3 스프링 빈 조회 - 상속 관계

  • 부모 타입으로 조회하면, 자식 타입도 함께 조회
  • 그래서 자바 객체의 최고 부모인 Object 타입으로 조회하면, 모든 스프링 빈을 조회한다.

특정 하위 타입을 조회

void findBeanBySubType() {
 	RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);
 	assertThat(bean).isInstanceOf(RateDiscountPolicy.class);
 }

특정 하위 타입을 조회

void findAllBeanByParentType() { 
	Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
 	assertThat(beansOfType.size()).isEqualTo(2);
 	for (String key : beansOfType.keySet()) {
 		System.out.println("key = " + key + " value=" + beansOfType.get(key));
 	}
 }

3. 스프링 빈 설정 메타 정보


스프링은 자바 코드, XML 등 다양한 설정 형식을 지원하는데, 이를 지원 할 수 있는 이유는 BeanDefinition 이라는 추상화가 있어서이다.

Bean_Definition

  • 스프링 컨테이너는 확장자 명을 모르더라도 BeanDefiniton 만 생성하면 된다.
  • 스프링 컨테이너는 @Bean, <bean> 등 각각 하나씩 메타 정보를 생성하고 이를 기반으로 빈을 생성한다.

Code level 에서 보자면
Bean_Definition version.code

  • AnnotationConfigApplicationContextAnnotatedBeanDefinitionReader 를 사용해서 AppConfig.class 를 읽고 BeanDefinition 을 생성한다.

  • GenericXmlApplicationContextXmlBeanDefinitionReader 를 사용해서 appConfig.xml 설정 정보를 읽고 BeanDefinition 을 생성한다.

  • 새로운 형식의 설정 정보가 추가되면, ---BeanDefinitionReader 를 만들어서 BeanDefinition 을 생성하면 된다.


<출처 : 스프링 핵심 원리 - 기본편 by 김영한>

profile
내 맘대로 끄적이는 개발 블로그

0개의 댓글