Spring Container (ApplicationContext)

김신영·2023년 10월 7일
0

SpringFramework

목록 보기
1/4
post-thumbnail

ApplicationContext

  • Spring Container 인터페이스
  • 구현체 예시 목록
    • AnnotaionConfigApplicationContext
    • GenericXmlApplicationContext
    • GenericGroovyApplicationContext
    • StaticApplicationContext
  • ISP (Interface Segregation Principle)
    • BeanFactory
      • Bean을 관리하고 조회하는 역할
      • ListableBeanFactory
      • HierarchicalBeanFactory
    • EnvironmentCapable
      • 로컬, 개발, 운영 등을 구분해서 환경변수를 관리하는 역할
    • ResourceLoader
      • 파일, classpath, 외부 등에서 Resource를 관리하고 조회하는 역할
      • ResourcePatternResolver
    • MessageSource
      • 메시지를 다국어로 처리하는 기능을 담당하는 역할
    • ApplicationEventPublisher
      • 이벤트를 발행하고 구독하는 모델을 편리하게 지원하는 역할

application-context.png

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
        // ...
}

ApplicationContext 클래스 다이어그램

AnnotationConfigApplicationContext.png

다양항 설정 형식 지원

  • Annotation
  • XML
  • ...

application-context-impl.png

Spring Container 생성 과정

  1. Spring Bean을 생성한다.
  2. Spring Bean들의 의존관계를 주입한다.

spring-container-step1.png

spring-container-step2.png

spring-container-step3.png

spring-container-step4.png

Spring Container에 등록된 모든 Bean 조회

  • ApplicationContext::getBeanDefinitionNames() : 등록된 모든 Bean 이름 조회
  • 코드 예시
class ApplicationContextTests {
  @Test
  @DisplayName("Application Bean 출력하기")
  void findApplicationBean() {
    String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();

    for (String beanDefinitionName : beanDefinitionNames) {
      BeanDefinition beanDefinition
              = applicationContext.getBeanDefinition(beanDefinitionName);

      if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
        Object bean = applicationContext.getBean(beanDefinitionName);
        System.out.println("name = " + beanDefinitionName + ", bean = " + bean);
        System.out.println("beanDefinition = " + beanDefinition);
      }
    }
  }
}

Spring Bean 조회

Bean 이름으로 조회

  • ApplicationContext::getBean(beanName)
  • 해당 이름으로 등록된 Bean이 없는 경우
    • NoSuchBeanDefinitionException 예외 발생
  • 코드 예시

Bean 이름, Bean 타입으로 조회

Bean 타입으로 조회

  • ApplicationContext::getBean(beanType)
    • 같은 타입의 Bean이 2개 이상 등록된 경우
      • NoUniqueBeanDefinitionException 예외 발생
  • 코드 예시

동일한 타입 둘 이상의 Bean 조회

  • ApplicationContext::getBeansOfType(beanType) : Map<String, T>
  • 코드 예시

Spring Bean 조회 - 상속관계

  • 부모 타입으로 조회하면, 자식 타입도 함께 조회한다.
  • 코드 예시

BeanDefinition

  • Bean의 메타데이터 정보를 담고 있는 인터페이스

BeanClassName

  • BeanClassName : String
    • 생성할 Bean의 클래스 명

Bean Scope

  • Scope : int
    • 기본값: SCOPE_SINGLETON
    • SCOPE_SINGLETON
    • SCOPE_PROTOTYPE

Lazy Initialization

  • LazyInit : boolean

DependsOn

  • DependsOn : String[]
    • 해당 Bean이 생성되기 전에 먼저 생성되어야 하는 Bean의 이름

Autowire Candidate

  • AutowireCandidate : boolean
    • 해당 Bean을 다른 Bean의 의존성 주입 후보로 사용할지 여부

Primary

  • Primary : boolean
  • 같은 타입의 Bean이 여러 개 등록된 경우, 우선권을 가지는 Bean을 설정
  • @Autowired 어노테이션을 사용할 때 우선권을 가지는 Bean을 주입한다.

Factory Bean Name, Factory Method Name

  • FactoryBeanName : String
    • 해당 Bean을 생성하는 Factory Bean의 이름
    • ex: @Configuration 어노테이션을 가진 Bean의 이름
  • FactoryMethodName : String
    • 해당 Bean을 생성하는 Factory Method의 이름

Constructor Argument Values, Property Values

  • ConstructorArgumentValues : ConstructorArgumentValues
    • 생성자를 통해 Bean을 생성할 때 사용할 인자 정보
  • PropertyValues : MutablePropertyValues

Init Method Name, Destroy Method Name

  • InitMethodName : String
    • Bean 생성 후 호출할 초기화 메서드 이름
  • DestroyMethodName : String
    • Bean 소멸 전 호출할 메서드 이름

Role

  • Role : int
    • ROLE_APPLICATION : 일반적으로 사용자가 정의한 Bean
    • ROLE_INFRASTRUCTURE : 스프링 내부에서 사용하는 Bean
    • ROLE_SUPPORT

Spring Container 와 Singleton Bean

  • Spring Container는 기본적으로 모든 Bean을 Singleton으로 관리한다.
  • Bean Scope 설정에 따라 다른 Lifecycle을 가진 Bean을 생성할 수 있다.
    • SCOPE_SINGLETON
    • SCOPE_PROTOTYPE

spring-container-singleton-bean.png

Singleton 방식의 주의사항

  • Singleton 객체는 stateless 하게 설계해야 한다.
    • 특정 클라이언트에 의존적인 필드가 있으면 안된다.
    • 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
    • 가급적 읽기만 가능해야 한다.
    • 공유되는 필드가 있다면, Thread-safe 하게 설계해야 한다.
      • Local Variable, Method Parameter, ThreadLocal 등을 사용해야 한다.

@Configuration과 바이트코드 조작

  • @Configuration 어노테이션을 가진 Bean은 CGLIB 라이브러리를 사용하여 바이트코드를 조작한다.
  • 만약 @Configuration 어노테이션을 제거한다면, Singleton Bean으로 등록되지 않는다.
    • CGLIB 라이브러리를 통해 바이트코드 조작이 되지 않기 때문이다.

configuration-cglib-proxy-bean.png

profile
Hello velog!

1개의 댓글

comment-user-thumbnail
2023년 10월 7일
답글 달기