스프링 전반적인 기술을 주제로 사내 세미나를 하였다. 따라서 이를 공식 문서를 보면서 복습하면서 다시 정리해보았다.

Screen Shot 2021-03-24 at 6 18 09 PM

  • 스프링 코어 문서 가장 첫 부분에 나와있는 문구이다. 전체적인 기술을 다루지만 특히 스프링 프레임워크의 IoC(Inversion of Control) 컨테이너가 가장 중요하다고 나와있다.

  • Spring Framework의 IoC 컨테이너에 대한 처리는 SpringAOP(Aspect-Oriented Programmin) 기술을 밀접하게 따르고 있다고 한다.

  • 스프링 프레임워크는 개념적으로 이해하기 쉽고 자바 엔터프라이즈 프로그래밍에서 AOP 요구사항의 80%를 성공적으로 해결하는 AOP 프레임워크가 있다.

스프링 IoC 컨테이너 및 빈(Bean)


Screen Shot 2021-03-24 at 6 26 06 PM

  • 이 장에서는 제어의 반전(IoC) 원칙의 스프링 프레임워크 구현에 대해서 다룬다.
  • IoC는 의존성 주입이라고 알려져 있다. (DI)
  • DI는 객체가 생성자 파라미터, 펙토리 메서드에서 반환된 후 객체 인스턴스에 설정된 속성을 통해서만 객체의 종속성을 정의하는 프로세스이다.
  • 그런 다음에, 컨테이너가 빈을 생성할 때, 이러한 종속성을 주입한다.
  • 이러한 프로세스는 기본적으로 클래스 직접 구성이나 서비스 로케이터 패턴과 같은 매커니즘을 이용하여, 종속성의 인스턴스 화를 한다.
  • org.springframework.beansorg.springframework.context 패키지들이 스프링 프레임워크 IoC 컨테이너의 기본 구성을 이루고 있다.
  • BeanFactory 인터페이스는 모든 타입의 객체를 관리할 수 있는 고급 설정 매커니즘을 제공한다.
  • ApplicationContextBeanFactory의 서브 인터페이스이다.

ApplicationContextInterface

위와 같은 그림으로 이해하면 이해하기 편하다.

  • 간단히 말해서 BeanFactory는 구성 프레임워크와 기본 기능을 제공하며 Application Context는 더 많은 엔터프라이즈별 기능을 추가한다.

  • Spring에서는 애플리케이션의 핵심을 구성하고, Spring IoC 컨테이너에 의해서 관리되는 개체를 빈(Bean)이라고 한다.

  • 빈은 스프링 IoC 컨테이너에 의해서 인스턴스화, 조립 및 관리되는 객체이다.

  • 그렇지 않으면 빈(Bean)은 응용 프로그램의 여러 객체에 불과하다.

  • 빈과 빈 사이의 종속성은 컨테이너가 사용하는 설정 메타데이터에 의해서 반영된다.

컨테이너 개요


Screen Shot 2021-03-24 at 6 46 34 PM

  • org.springframework.context.ApplicationContextSpring Ioc 컨테이너를 나타내며 빈의 인스턴스화 및 구성 및 조립을 담당한다.

  • 컨테이너는 메타데이터 설정을 읽어서, 인스턴스화, 구성 및 조립할 객체에 대한 지침을 가져온다.

  • 구성 메타데이터는 XML, Java 어노테이션 또는 Java 코드로 표시된다.

  • 애플리케이션을 구성하는 객체와 이러한 객체간의 풍부한 상호 종속성을 표현할 수 있다.

container-magic

  • 위의 그림은, 스프링 IoC 컨테이너가 빈 설정정보를 읽어서, ApplicationContext 생성되고 초기화되면 완전히 구성되고 실행 가능한 시스템 또는 응용 프로그램의 생성을 나타낸다.

빈의 스코프와 라이프 사이클(Bean Scope and LifeCycle)


Screen Shot 2021-03-24 at 7 10 07 PM

  • 스프링 IoC 컨테이너는 하나 이상의 빈을 관리한다. 이러한 빈은 컨테이너에 제공하는 메타데이터 XML <bean/> 형식으로 제공된다.

  • 컨테이너 자체 내에서 이러한 빈 정의는 BeanDefinition 객체로 표시되며, 여기에는 (다른 정보 중에서도) 다음과 같은 메타데이터가 포함된다.

    • 클래스 이름: 정의되는 빈의 실제 구현 클래스이다.
    • 빈이 클래스에서 어떻게 동작해야하는지를 나타내는 동작 구성 요소이다. (범위, 라이프 사이클 콜백 등).
    • 빈이 동작하는데 의존성을 가지는 다른 빈에 대한 참조이다. 이러한 참조를 collaborators 또는 dependencies 라고 한다.
    • 새로 생성된 개체에서 설정할 기타 구성 설정(예: 풀의 크기 제한 또는 연결 풀을 관리하는 빈에서 사용할 연결 수)

Screen Shot 2021-03-24 at 7 17 00 PM

위의 표는 빈의 정의를 나타내고 속성은 다음과 같다.

  • Class: Bean을 생성하기 위한 클래스를 말한다.
  • Name: Bean의 이름을 말한다. Bean이 누군가에 의해 참조되어야 할 때 사용된다.
  • Scope: Bean의 생명주기와 관련하여 어느 Scope에 유일하게 존재할 것이냐에 대한 정의이다.
  • Constructor arguements: 빈의 생성자로 의존성을 명시 하는 방법이다.
  • Properties: Bean의 생성자로 의존성을 명시하는 방법이다.
  • Autowiring: Autowiring에 대한 방법을 명시하는 방법이다.
  • Lazy initializaton: Lazy 하게 Bean을 초기화 시키도록 명시하는 방법이다.
  • Initialization method: Bean 초기화 시에 호출되는 LifeCycle 메서드를 말한다.
  • Destuction method: Bean 파괴 시에 호출되는 LifeCycle 메서드를 말한다.

Screen Shot 2021-03-24 at 7 31 54 PM

  • singleton: (Default) SPRING IoC 컨테이너당 하나의 레퍼런스만 존재하는 스코프입니다.
  • prototype: 임의의 수의 객체 인스턴스로 단일 빈의 범위를 지정한다.
  • request: 단일 빈 정의의 범위를 단일 HTTP 요청의 수명 주기로 지정한다, 각, HTTP 요청에는 단일 빈 정의 뒤에 생성된 빈 인스턴스가 있다, 오직 ApplicationContext에서만 유효하다.
  • session: 단일 빈 정의의 범위를 HTTP 세션의 생명주기로 지정한다. 오직 웹의 ApplicationContext에서만 유효하다.
  • application: 단일 빈의 정의를 서블릿 컨텍스트의 생명주기에 범위를 지정한다. 웹의 ApplicationContext 에서만 유효하다.
  • websocket: 단일 bean의 정의를 WebSocket의 생명 주기에 범위를 지정한다. 웹의 ApplicationContext에서만 유효하다.

빈의 생명 주기 콜백(Lifecycle Callbacks)


Screen Shot 2021-03-25 at 8 41 23 AM

  • 컨테이너의 빈 생명주기와 상호 작용하기 위해서 InitializingBean, DisposableBean 인터페이스를 구현할 수 있다.

  • 컨테이너는 빈을 초기화 하기 전에 afterPropertiesSet()을 호출하고 Bean 소멸시에 destory()를 호출하여 특정 작업을 수행하게 할 수 있다.

JSR-250 스펙에서는 @PostConstruct, @PreDestory 어노테이션을 사용하는데, 일반적으로 최신 스프링 애플리케이션에서 생명 주기 콜백을 수신하기 위한 좋은 방법이다. 어노테이션을 사용한다는 것은 스프링이 특정 인터페이스에 결합되지 않는다는 것을 의미한다.

  • 내부적으로 SpringFrameworkBeanPostProcessor 구현을 사용하여 적절한 메서드를 찾아 호출할 수 있는 모든 콜백 인터페이스를 처리한다.

  • 커스텀 기능이 필요하거나, 스프링이 기본적으로 제공하지 않는 다른 라이프 사이클 동작이 필요한 경우 BeanPostProcessor를 직접 구현할 수 있다.

Screen Shot 2021-03-25 at 8 54 29 AM

  • InitializingBean 인터페이스는 불 필요하게 코드를 스프링에 연결하므로 사용하지 않는 것이 좋다.

  • 또는 @PostConstruct 주석을 사용하거나 POJO 초기화 방법을 지정하는 것이 좋다.

  • XML 기반 구성 메타 데이터의 경우 init-method 속성을 사용하여 인수없는 빈 서명이 있는 메서드의 이름을 지정할 수 있다.

  • Java 설정으로는 @BeaninitMethod 속성을 사용할 수 있다.

public class AnotherExampleBean implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        // do some initialization work
    }
}

여러 가지 방법으로 구현할 수 있지만, 인터페이스 방법은 권장하지 않는 방법이다.

Screen Shot 2021-03-25 at 9 00 11 AM

org.springframework.beans.factory.DisposableBean 인터페이스를 구현하면 이를 포함하는 컨테이너가 소멸될 때, Bean이 콜백을 받을 수 있다.

  • DisposableBean 인터페이스는 단일 메서드를 지정한다.

  • 초기화와 같이 인터페이스 구현은 불필요하게 코드를 스프링에 연결하므로 사용하지 않는 것이 좋다.

  • 또는 @PreDestory 주석을 사용하거나 빈 정의에서 지원하는 일반 메서드를 지정하는 것이 좋습니다.

public class AnotherExampleBean implements DisposableBean {

    @Override
    public void destroy() {
        // do some destruction work (like releasing pooled connections)
    }
}

Screen Shot 2021-03-25 at 9 19 57 AM

  • 스프링 고유의 InitializingBean 또는 DisposableBean 콜백 인터페이스를 사용하지 않는 초기화 및 폐기 메서드 콜백을 작성할 때는 일반적으로 init(), initialize(), dispose()등과 같은 이름으로 작성한다.

  • 이상적으로는 이러한 수명주기 콜백 메서드의 이름은, 모든 개발자가 동일한 메서드 이름을 사용하고 일관성을 보장하기 위함이다.

그렇다면 InitializingBean과 DisposableBean 인터페이스를 구현하는 것과 @PostConstruct, @PreDestory를 사용하는 것의 차이점은 무엇일까?

참고 문헌

>> Home