Documents

IoC Container

IoC 컨테이너

  • 스프링 어플리케이션에서는 오브젝트의 생성과 관계설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 독립된 컨테이너가 담당

  • 컨테이너가 코드 대신 오브젝트에 대한 제어권을 갖고 있어서 스프링 컨테이너를 IoCInversion of Control 컨테이너 라고도 함

  • 스프링에서 IoC를 담당하는 컨테이너를 빈 팩토리 또는 애플리케이션 컨텍스트 라고 부르기도 함

    • 오브젝트의 생성과 오브젝트 사이의 럼타임 관계를 설정하는 DI 관점으로 볼 때 빈 팩토리 라고 함, 하지만 스프링 컨테이너는 단순한 DI 작업보다 더 많은 일을 함

    • DI를 위한 빈 팩토리에 엔터프라이즈 애플리케이션을 개발하는 여러 가지 컨테이너 기능을 추가한 것을 애플리케이션 컨텍스트 라고 함

  • 스프링의 IoC 컨테이너는 일반적으로 애플리케이션 컨테스트 를 말함

  • 스프링에서 빈 팩토리(BeanFactory)와 애플리케이션 컨테스트(ApplicationContext) 인터페이스가 정의되어 있음

    • ApplicationContext 인터페이스는 BeanFactory 인터페이스를 상속한 서브인터페이스

      The ApplicationContext.java in spring-context-4.3.21.RELEASE
      public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
          MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    • 실제로 스프링 컨테이너(또는 IoC 컨테이너)라고 말하는 것은 바로 이 ApplicationContext 인터페이스를 구현한 클래스의 오브젝트

  • 스프링 애플리케이션은 최소한 하나 이상의 애플리케이션 컨텍스트 오브젝트 를 갖고 있음

IoC 컨테이너를 사용하는 애플리케이션 생성하기

  • 만들어진 컨테이너가 본격적인 IoC 컨테이너로서 동작하려면 POJOPlain Old Java Object 클래스설정 메타정보 가 필요함

    • POJO 코드를 설계할 때는 일단 유연한 변경 가능성을 고려해서 만듬

    • POJO는 특정 기술과 스펙에서 독립적일뿐더러 의존관계에 있는 다른 POJO와 느슨한 결합Loose Coupling을 갖도록 만들어야 함

  • 애플리케이션에서 사용할 것을 선정하고 이를 IoC 컨테이너가 제어할 수 있도록 적절한 메타정보 를 만들어야 함

  • IoC에서 가장 기초적인 역할은 오브젝트를 생성하고 관리하는 것

    • 스프링 컨테이너가 관리하는 오브젝트를 bean 이라고 부름

  • 스프링이 XML에 담김 내용을 읽어서 설정 메타정보로 활용하는 것이지, XML로 된 설정 메타정보를 가졌다는 말은 틀림

    • 스프링의 설정 메타정보는 BeanDefinition 인터페이스로 표현되는 순수한 추상 정보

    • 즉, XML에 종속되지 않고 BeanDefinition 으로 정의되는 스프링의 설정 메타 정보의 내용을 표현한 것이 있다면 어떤 형식이든 사용 가능

The Spring IoC container

WebApplicationContext

  • 스프링 애플리케이션에서 사장 많이 사용되는 애플리케이션 컨텍스트

  • 웹에서 자바 VM 에게 main() 메소드를 가진 클래스를 시작시켜 달라고 요청할 수 없음, 게다가 사용자도 여럿이며 동시에 웹 애플리케이션 사용

    • 웹 환경에서는 main() 메소드 대신 서블릿 컨테이너 가 브라우저로부터 오는 HTTP 요청을 받아서 해당 요청에 매핑되어 있는 서블릿을 실행해주는 방식으로 동작

    • 서블릿이 일종의 main() 메소드와 같은 역할

  • 스프링은 웹 환경에서 애플리케이션 컨텍스트를 생성하고 설정 메타정보를 초기화하고, 클라이언트로부터 들어오는 요청마다 적절한 빈을 찾아서 실행시켜주는 기능을 가진 DispatcherServlet 을 제공

    • web.xml 에 등록하는 것만으로 웹 환경에서 스트링 컨테이너가 만들어지고 애플리케이션을 실행하는 데 필요한 대부분의 준비가 가능함

spring overview

  • 몇 개의 서블릿이 중앙집중식으로 모든 요청을 다 받아서 처리하는 방식을 프론트 컨트롤러 패턴 이라고 함

  • 서버에서 작동하는 애플리케이션에서 스프링 IoC 컨테이너를 사용하는 방법은 크게 3 가지

    1. 엔터프라이즈 애플리케이션 레벨에 두는 방법(1 가지)

    2. 웹 모듈 안에 컨테이너를 두는 것(2 가지)

      일반적으로 위 두가지 방식을 모두 사용해 컨테이너를 만듬.
      그래서 스프링 웹 어플리케이션에는 두 개의 컨테이너, 즉 WebApplicationContext 오브젝트가 만들어짐

      1. 스프링 애플리케이션의 요청을 처리하는 서블릿 안에서 만들어지는 것

      2. 웹 애플리케이션 레벨에서 만들어지는 것

  • 웹 애플리케이션 레벨에 등록되는 컨테이너는 보통 루트 웹 애플리케이션 컨텍스트 라고 함

    • 서블릿 레벨에 등록되는 컨테이너들의 부모 컨텍스트가 됨

    • 일반적으로 전체 계층구조 내에서 가장 최상단에 위치하기 때문

웹 애플리케이션의 컨텍스트 구성 방법

  • 서블릿 컨텍스트와 루트 애플리케이션 컨텍스트 계층구조

    • 컨텍스트 계층구조를 만드는 것

    • 스프링 웹 기능을 사용하는 경우 적용 가능

  • 루트 애플리케이션 컨텍스트 단일구조

    • 컨텍스트를 하나만 사용하는 방법

    • 스프링 웹 기술을 사용하지 않을 때 적용 가능한 방법

  • 서블릿 컨텍스트 단일구조

    • 컨텍스트를 하나만 사용하는 방법

    • 스프링 웹 기능을 사용하는 경우 적용 가능

루트 애플리케이션 컨텍스트 등록하기

  • 루트 웹 애플리케이션 컨텍스트 는 웹 애플리케이션 레벨에 만들어짐

  • 만드는 가장 간단한 방법은 서블릿의 이벤트 리스너event listener를 이용하는 것

  • 스프링은 웹 애플리케이션의 시작과 종료 시 발생하는 이벤트를 처리하는 리스너인 ServletContextListener 를 이용

    • 스프링은 이것을 구현한 ContextLoaderListener 를 제공

      public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
  • ContextLoaderListener 를 이용하는 간단한 방법

    web.xml 파일 안에 아래와 같이 리스너 선언을 넣어주면 됨

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    • 애플리케이션 컨텍스트 클래스: XmlWebApplicationContext

    • XML 설정파일 위치(default): /WEB-INF/applicationContext.xml

contextConfigLocation

<context-param>
    <param-nama>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/daoContext.xml
        /WEB-INF/applicationContext.xml
        classpath*:/META-INF/spring/context.xml
        classpath:applicationContext.xml
    </param-value>
</context-param>
  • 디폴트 XML 설정파일 위치를 변경하는 컨텍스트 파라미터

  • 접두어를 붙히지 않으면 웹 어플리케이션의 서블릿 리소스 패스로부터 파일 참조

  • 클래스패스로부터 설정파일을 찾을 경우 classpath: 를 붙혀서 참조 가능

  • ANT 스타일의 경로표시 방법 이용 가능: /WEB-INF/*Context.xml, /WEB-INF/**/*Context.xml

classpath* vs classpath

classpath

현재 프로젝트의 classpath만 참조

classpath*

현재 프로젝트뿐만 아니라 상위 classloader를 모두 검색하여 참조

spring