[우아한테크코스] 8월 24일 TIL

2 minute read

[Spring] Bean의 생명주기와 초기화 방법

Bean의 생명주기

Spring Container가 관리하는 객체로 주로 공유되어 사용되는 상태를 가지지 않는 클래스를 빈으로 등록해서 사용하게 된다. 여기서 객체들을 관리한다는 것은 단순히 singletone으로 객체를 제공하고 주입하는 것 뿐만 아니라 객체의 생성부터 소멸까지의 생명주기를 관리하는 것이다.

  • Bean

    Spring IoC가 직접 생성과 제어를 담당하는 오브젝트

  • BeanFactory

    Spring IoC를 담당하는 핵심 컨테이너로 Bean을 등록, 생성, 조회, 반환 등의 관리를 담당한다.

    이를 확장한 ApplicationContext를 사용한다. getBean() 메서드 정의하는 인터페이스

    해당 클래스에서는 Bean이 사용될 때 만들어지는 lazy loading이 사용된다.

    잘 사용되지 않는, 특수한 환경에서만 동작해도 되는 Bean의 경우 이 BeanFactory를 사용하는 것이 적절하다.

  • ApplicationContext

    BeanFactory를 확장한 IoC 컨테이너로 BeanFactory의 기능 뿐만 아니라 각종 다른 기능도 제공한다.

    해당 클래스에서는 Bean이 사용되기 전에 만들어지는 pre loading이 사용된다.

    대다수 이 ApplicationContext를 사용하는 것이 적절하다.

    스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 사용 -> 사용 -> 소멸 콜백 사용 -> 스프링 컨테이너 종료

image

  • Bean의 생명주기를 IoC 컨테이너에 위임하는 법

    @Bean 메서드 레벨 선언, 반환되는 객체를 개발자가 수동으로 빈 등록, 관리 불가능한 외부 라이브러리 사용 시

    @Component 클래스 레벨 선언, 스프링 런타임 시 ComponentScan을 통해 자동으로 빈 찾고 등록, 개발자 클래스 사용 시

    기타 다른 어노테이션을 이용한 빈 생성

직접 Bean의 생명주기를 관리하는 방법

Spring IoC 컨테이너는 Bean 객체의 생명 주기를 컨테이너 생명 주기 내에서 관리하고 객체 생성이나 소멸 직전 호출되는 콜백 메서드 제공

객체를 직접 소멸해주는 것은 데이터베이스 커넥션과 같은 자원을 해제하는 경우에 유용하게 사용할 수 있다.

  1. 인터페이스 InitializingBean, DisposableBean 사용
public class SomeBean implements InitializingBean, DisposableBean{
	//...
  @Override
  public void afterPropertiesSet() throws Exception {
    System.out.println("초기화");
  }
  
  @Override
  public void destroy() throws Exception {
    System.out.println("소멸");
  }
}

afterPropertiesSet(): InitializingBean 인터페이스에 대한 구현으로 빈 생성 후 의존관계 주입이 완료되면 호출된다.

destroy(): DisposableBean 인터페이스에 대한 구현으로 Spring Context가 내려가기 전에 호출된다.

하지만 인터페이스 구현은 코드에 지장이 갈 뿐만 아니라 메서드명을 수정할 수도 없는 스프링에 의존적인 구현이 된다.

  1. @Bean 어노테이션에 initMethod, destroyMethod 속성 사용

    ` @Bean(initMethod = “construct”, destroyMethod = “destroy”)`

    위와 같이 속성을 전해주고 아래와 같이 그 속성에 대한 메서드를 bean 설정 클래스에서 전달해주어야 한다. xml이나 configuration에서 지정이 필요하다.

//...
public void construct(){
  System.out.println("초기화");
}

public void destroy() {
  System.out.println("소멸");
}
//...

destroyMethod가 없으면 Context가 자동으로 종료 메서드들의 이름인 것을 호출해 동작한다. 싫으면 “”

  1. @PostConstruct, @PreDestroy 어노테이션 사용

    ```java //… @PostConstruct public void construct(){ System.out.println(“초기화”); }

@PreDestroy public void destroy() { System.out.println(“소멸”); } //… ```

spring에서 가장 권장하는 방식으로 java 표준 어노테이션이라 편리하게 사용할 수 있다.

postConstruct는 초기화 시점에, preDestroy는 소멸 시점에 원하는 동작을 하도록 bean 내에 위의 함수와 어노테이션을 작성해주면 된다.

결론적으로 우리가 만들어서 사용하는 bean들이 존재함으로써 메모리를 잘 잡아먹어서 소멸시켜줄 필요성이 있는 db 연결과 같은 Bean들은 위와 같은 작업을 통해 소멸되도록 설정해주는 작업이 별도로 필요하다.

그 외에 Bean들은 Spring IoC에서 제공하는 기능으로 사용해도 무방하다.

참고