Spring Bean Life Cycle

정체는 김태현·2022년 10월 4일
0

항해99

목록 보기
5/38

Spring Bean Event Life Cycle

  1. 스프링 컨테이너 생성 -> 빈 생성 -> 의존관계 주입 -> 초기화 콜백 메서드 호출
    -> 애플리케이션에서 빈 사용 -> 소멸 전 콜백 메서드 호출 -> 스프링 종료

  2. 스프링은 의존관계 주입이 완료될 경우 스프링 빈에게 콜백 메서드를 통해서
    초기화 시점을 알려준다

  3. 스프링 컨테이너가 종료 되기 직전에 소멸 전 콜백 메서드를 통해 소멸 시점을 알려준다.



빈 객체의 라이프 사이클(Life Cycle of Bean Object)

스프링 컨테이너(Spring Container)는 빈 객체(Bean Object)를 생성하고, 프로퍼티(Property)를 할당하고, 초기화를 수행하고, 사용이 끝나면 소멸시키는 일련의 과정을 관리합니다.

예를 들어 데이터베이스(Database, DB)에 대한 커넥션 풀(Connection Pool)을 제공하는 Bean은 사용되기 전에 일정 개수의 커넥션을 연결해야 하고, 애플리케이션(Application) 종료 시점에는 열려있는 커넥션을 모두 닫아야 하는데, 스프링 컨테이너는 이런 커넥션 생성과 종료 시점을 제어하게 됩니다.

스프링 컨테이너는 다음과 같은 2가지 방식을 이용해서 Bean의 라이프사이클을 관리할 수 있습니다.

  1. 스프링이 제공하는 특정 인터페이스를 상속받아 Bean을 구현합니다.

  2. 스프링 설정에서 특정 메서드를 호출하라고 지정합니다.

스프링은 라이프사이클에 특화된 인터페이스를 제공하고 있습니다. 예를 들어, 스프링은 InitalizingBean 인터페이스를 제공하고 있으며, Bean 객체의 클래스(Class)가 InitalizingBean 인터페이스(Interface)를 구현(Implement)하고 있으면 InitalizingBean 인터페이스에 정의된 메서드(Method)를 호출해서 Bean 객체가 초기화를 진행할 수 있도록 합니다. 또한, 스프링 설정에서 초기화 메서드를 지정하면, 스프링은 그 메서드를 호출해서 Bean이 초기화를 수행할 수 있게 합니다.

Bean 객체의 초기화뿐만 아니라 Bean 객체의 소멸 과정 등 Bean의 라이프사이클을 관리할 수 있도록 스프링은 인터페이스와 설정 방법을 제공하고 있습니다.

개요

스프링 컨테이너는 빈 객체(Bean Object)를 생성하고 초기화하고 소멸시킬 때 다음과 같은 순서대로 Bean 객체의 메서드(Method)를 실행합니다.

빈 객체 라이프 사이클(Bean Object Life Cycle)

참고로 배경 색이 흰색인 단계는 Bean 객체의 메서드를 호출하는 것을 의미합니다.

위의 그림의 전체 흐름은 [객체 생성/프로퍼티 설정 → 초기화 → 사용 → 소멸] 의 4단계를 거치는 것을 알 수 있습니다. 컨테이너는 Bean 객체를 생성하고 프로퍼티를 설정한 뒤에 Bean의 초기화를 진행하며, 컨테이너를 종료하는 과정에서 생성한 Bean 객체의 소멸 과정을 진행합니다.

Bean의 초기화와 소멸 방법은 각각 3가지가 존재하며, 각 방식이 쌍을 이루어 함께 사용되곤 합니다. 즉, @PostConstruct 어노테이션(Annotation)을 사용해서 초기화 메서드를 지정했다면, @PreDestroy 어노테이션을 사용해서 소멸 메서드를 지정하고, 커스텀 init 메서드를 사용했다면, 커스텀 destroy 메서드를 사용하는 식입니다. 참고로 초기화와 소멸 방식을 다르게 해도 문제가 되지는 않습니다.



빈 생명주기 콜백 종류 3가지

  1. 스프링에서 제공하는 인터페이스 (InitializingBean, DisposableBean)
  2. 설정 정보에서 초기화 메서드, 종료 메서드 지정하는 방법
  3. @PostConstruct, @PreDestroy 어노테이션

1.스프링에서 제공하는 인터페이스

   public class ExampleBean implements InitializingBean, DisposableBean {
    // 중략
    
     @Override
      public void afterPropertiesSet() throws Exception {
        // 초기화 
      }
      
  @Override
  public void destroy() throws Exception {
    // 메모리 반납, 연결 종료와 같은 과정 
  	}
  }

이 방식의 단점

  • 스프링 전용 인터페이스에 코드가 의존
  • 메서드를 오버라이드하기 때문에 메서드명 변경 불가능
  • 코드를 커스터마이징할 수 없는 외부 라이브러리에 적용 불가능

2. 설정 정보에서 초기화 메서드, 종료 메서드 지정하는 방법

public class ExampleBean {

  // 중략

  public void initialize() throws Exception {
    // 초기화 
  }

  public void close() throws Exception {
    // 메모리 반납, 연결 종료와 같은 과정 
  }
}

@Configuration
static class LifeCycleConfig {

  @Bean(initMethod = "initialize", destroyMethod = "close")
  public ExampleBean exampleBean() {
    // 생략
  }
} 

이 방식의 장점

  • 메서드 이름을 자유롭게 부여 가능
  • 스프링 코드에 의존하지 않음
  • 설정 정보를 사용하기 때문에 코드를 커스터마이징 할 수 없는 외부 라이브러리에서도 적용 가능

이 방식의 단점

  • Bean 지정 시 initMethod와 destroyMethod를 직접 지정해야 하는 번거로움

@Bean의 destroyMethod 속성의 특징

  • 라이브러리는 대부분 종료 메서드명이 close 혹은 shutdown
  • @Bean의 destroyMethod는 기본값이 inferred (추론)으로 등록 즉, close, shutdown라는
  • 이름의 메서드가 종료 메서드라고 추론하고 자동으로 호출해줌
  • 즉, 종료 메서드를 따로 부여하지 않더라도 잘 작동
  • inferred 기능을 사용하기 싫다면 명시적으로 destoroyMethod="" 와 같이 공백을 지정해줘야 함

3. @PostConstruct, @PreDestroy 어노테이션

public class ExampleBean {

  // 중략

  @PostConstruct
  public void initialize() throws Exception {
    // 초기화 
  }

  @PreDestroy
  public void close() throws Exception {
    // 메모리 반납, 연결 종료와 같은 과정 
  }
}

@Configuration
static class LifeCycleConfig {

  @Bean
  public ExampleBean exampleBean() {
    // 생략
  }
}

이 방식의 장점

  • 최신 스프링에서 권장하는 방법!
  • 어노테이션만 붙이면 되기 때문에 편리함
  • 스프링에 종속적인 기술이 아니라 자바 표준 코드이기 때문에 다른 컨테이너에서도 동작
  • 컴포넌트 스캔과 잘 어울림

이 방식의 유일한 단점

  • 커스터마이징이 불가능한 외부 라이브러리에서 사용 불가능 (외부 라이브러리에서 초기화, 종료를 해야 할 경우 두 번째 방법 즉, @Bean의 initMethod와 destroyMethod 키워드를 사용)

참고: https://jaimemin.tistory.com/1787
참고: https://blog.naver.com/dktmrorl/222170823315

profile
하나부터 열가지 다

0개의 댓글

관련 채용 정보