Spring & SpringBoot

스프링 컨테이너(Spring Container)

Hyeonni 2022. 10. 19. 21:17

 

스프링 컨테이너(Spring Container)

스프링에서는 스프링 컨테이너를 통해 객체를 관리한다. 그리고 스프링 컨테이너를 통해 관리되는 객체를 빈(Bean)이라고 한다.스프링 컨테이너는 스프링 프레임워크의 핵심 컴포넌트로 애플리케이션 빈의 생명주기(생성, 관리, 제거)를 담당한다.
스프링 컨테이너는 개발자가 정의한 Bean을 객체로 만들어 관리하고 개발자가 필요로 할 때 제공한다. 그리고 스프링 컨테이너를 통해 원하는 만큼의 객체를 가질 수 있다.
ApplicationContext를 스프링 컨테이너라고 하며, 다형성을 적용해 인터페이스로 구현되어 있다.
스프링 컨테이너는 XML, 애너테이션 기반의 자바 설정 클래스로 만들 수 있다. 

스프링 컨테이너가 의존성 주입을 통해 애플리케이션의 컴포넌트를 관리한다. 즉, 의존성이 있는 서로 다른 빈들을 연결하는 역할을 한다. 이것이 스프링이 제어 흐름의 역전(IoC)을 위해 의존성 주입(DI)을 해준다는 것이다. 이를 통해 모듈 간의 결합도가 낮아지고 개발자는 모듈 간에 의존 및 결합으로 인해 발생하는 문제로부터 자유로울 수 있다.

 

스프링 컨데이너의 종류

  • BeanFactory
    • 스프링 컨테이너의 최상위 인터페이스이다.
    • BeanFactory는 빈을 등록하고 생성하고 조회하고 돌려주는 등 빈을 관리하는 역할을 한다.
    • getBean() 메서드를 통해 빈을 인스턴스화 할 수 있다.
    • @ Bean 애너테이션이 붙은 메서드의 명을 스프링 빈의 이름으로 사용해 빈을 등록한다.
  • ApplicationContext

https://dev-aiden.com/spring/Spring-Container/

  • BeanFactory을 비롯한 여러 인터페이스를 상속받아 사용한다.
  • 인터페이스 설명
    • ResourcePatternResolver : 파일, 클래스 패스, 외부 등 리소스를 편리하게 조회하기 위한 인터페이스
    • EnvironmentCapable : 개발, 운영 등 환경 변수 등으로 나눠 처리하고, 애플리케이션 구동 시 필요한 정보들을 관리하기 위한 인터페이스
    • BeanFactory : 빈을 관리하고 검색하는 등 빈에 관한 인터페이스
    • MessageSource : 메시지 다국화(설정 값에 따라 각국의 언어로 변환)를 위한 인터페이스
    • ApplicationEventPublisher : 이벤트 관련 기능을 제공하는 인터페이스

BeanFactory를 사용하는 경우는 거의 없기에 일반적으로 ApplicationContext를 스프링 컨테이너라고 한다.

 

스프링 컨테이너의 생성 과정

 

https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html

1. 먼저 비어있는 스프링 컨테이너가 생성된다.
2. 스프링 설정 파일(Configuration Metadata)을 기반으로 컨테이너에 스프링 빈이 등록된다.
3. 스프링 설정 파일(Configuration Metadata)을 기반으로 스프링 빈의 의존관계를 주입(DI)한다.

Configuration Metadata란 애플리케이션 개발자가 Spring 컨테이너에 애플리케이션의 개체를 인스턴스화, 설정(configuration), 조립(assembling)하도록 지시하는 정보를 말한다. 주로 XML, 주석, 자바 애너테이션, 자바 코드 등의 형식으로 이루어져 있다.

추가적으로 무슨 Configuration Metadata를 사용하는 것이 좋냐는 의문이 들 수 있다. 스프링 공식 문서에서는 아래와 같이 설명하고 있다.

XML 기반 컨테이너 구성과 주석 기반 컨테이너 구성을 비교해보면 더 나은 것을 고를 수는 없지만, 주석 기반 방식은 선언에 많은 내용을 제공하여 더 짧고 간결한 구성을 할 수 있다는 점에서 장점이다.  XML의 경우에는 소스 코드를 건드리거나 다시 컴파일하지 않고 구성 요소를 연결하는 데 있어서 편리하다는 점이 장점이기에 때에 따라 적절하게 선택하여 사용하도록 권장한다.

 

애플리케이션 클래스(Business Objects)와 구성 메타데이터(Configuration Metadata)가 결합되어 위에서 설명한 방식으로 스프링 컨테이너(ApplicationContext)를 생성 및 초기화한 후에 완전히 구성되고,  최종적으로 실행 가능한 시스템/애플리케이션이 구성되게 된다.

 

컨테이너 인스턴스화

ApplicationContext 생성자의 인자로 Configuration Metadata를 넘겨주면 된다.

// Annotation
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

// XML
ApplicationContext context = new ClassPathXmlApplicationContext("appConfig.xml");

// XML
ApplicationContext context = new GenericXmlApplicationContext("appConfig.xml");

 

  • GenericXmlApplicationContext() VS ClassPathXmlApplicationContext()
    • GenericXmlApplicationContext()는 클래스 패스뿐만 아니라 다양한 소스로부터 설정파일을 읽어올 수 있다.
    • ClassPathXmlApplicationContext()는 XML파일을 클래스 패스에서 가져올 때 사용할 수 있는 편리한 가능이 추가된 것이다.
      • 클래스 패스의 경로 정보를 클래스에서 가져올 수 있는 기능이 존재한다.
ApplicationContext context = new GenericXmlApplicationContext("spring/member/dao/daoContext.xml");


ApplicationContext context = new ClassPathXmlApplicationContext("daoContext.xml", memberDao.class);

spring.member.dao 패키지에 daoContext.xml 파일과 memberDao.java 파일이 존재한다고 하자.
위 코드를 보면 GenericXmlApplicationContext()의 경우 전체 클래스 패스로부터 파일 경로를 적어줘야 하지만  ClassPathXmlApplicationContext()는 두번째 인자로 넘겨주는 클래스 객체의 경로로부터 상대 경로를 적을 수 있다.
즉, 같은 패키지에 있는 클래스 객체를 두 번째 인자로 넘겨준다면 Configuration Metadata 파일의 이름만 적어주면 되는 것이다.

 

만약 Configuration Metadata가 계층관계를 이루고 있다면 ClassPathXmlApplicationContext()는 상위 Context가 설정되기 전에 하위 Context를 새로 고치기 때문에 Bean을 찾을 수 없는 문제가 발생하여 빈 생성에 실패하는 경우가 발생한다고 한다. 그래서 자식 Context의 생성자에 부모 Context를 전달해야 한다 정상적으로 실행된다고 하니 이 점 주의해서 사용해야 한다.
위의 자세한 내용은 아래 링크에서 볼 수 있다.
https://stackoverflow.com/questions/63313382/genericxmlapplicationcontext-vs-classpathxmlapplicationcontext


https://dev-aiden.com/spring/Spring-Container/

https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/beans.html

https://frontierdev.tistory.com/81