[F-Lab 모각코 챌린지] 30일차 - Bean lifecycle (생성)

F-Lab 모각코 챌린지 30일차 - Bean lifecycle Spring 에서 Bean 의 생명주기를 개발자가 커스텀 하는 방법들과 순서를 기록 하였습니다.

[F-Lab 모각코 챌린지] 30일차 - Bean lifecycle (생성)

Spring 에서 Bean 의 생명주기 관리

Spring 에서는 Bean 의 생명주기는 여러 단계를 거쳐 생성 되며 개발자는 이 생명주기에 특정 로직을 주입하여 더 많은 제어를 할 수 있다

빈 생성 페이즈

1. Instantiation(인스턴스화)

자바에서 new 키워드로 객체를 생성하듯 Spring 이 Bean 의 클래스를 메모리에 인스턴스로 생성한다

2. Populate Properties(속성 설정)

Bean 에 정의된 속성들이 설정된다.

XML 구성 파일 또는 Java 구성 정보를 사용하여 설정 할 수 있다.

3. BeanNameAware & BeanFactoryAware 설정

특수 인터페이스인 BeanNameAware, BeanFactoryAware 를 구현한 클래스를 스캔하고 관련된 속성을 셋팅한다

위의 두 인터페이스를 구현하면 Spring 컨테이너에 의해 관리되는 Bean 의 추가 정보나 기능에 접근 할 수 있다.

3.1 BeanNameAware

BeanNameAware 를 구현하면 자신이 속한 Spring 컨테이너에서 사용되는 이름을 알 수 있다

package org.springframework.beans.factory;

public interface BeanNameAware extends Aware {

	void setBeanName(String name);

}
실제 코드이다. 주석은 제거했으며 위 패키지를 통해 찾아 볼 수 있다.

Spring 은 BeanNameAware 인터페이스를 구현하는 Bean 을 생성 할 때, 해당 Bean 의 이름을 setBeanName 메서드를 통해 주입한다

public class MyBean implements BeanNameAware {
    
    private String beanName;

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    // ...
}
예제 코드 3.1.0

3.2 BeanFactoryAware

BeanFactoryAware 를 구현하면 자신이 속한 Spring 컨테이너에 대한 참조를 얻을 수 있다.

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;

public interface BeanFactoryAware extends Aware {

	void setBeanFactory(BeanFactory beanFactory) throws BeansException;

}
실제 코드. 위와 같이 IDE 에서 검색하면 나온다

Spring 이 BeanFactoryAware 의 setBeanFactory(BeanFactory beanFactory) 메서드를 통해 해당 Bean 이 속한 BeanFactory 를 주입한다.

public class MyBean implements BeanFactoryAware {

    private BeanFactory beanFactory;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    // ...
}

Bean 이 필요한 경우 컨테이너에서 다른 Bean 을 조회하거나 컨테이너와 상호작용 할 수 있다.

4. BeanPostProcessor 전처리

BeanPostProcessor 인터페이스를 구현한 클래스의 전처리 메서드를 호출한다

package org.springframework.beans.factory.config;

import org.springframework.beans.BeansException;
import org.springframework.lang.Nullable;

public interface BeanPostProcessor {

  @Nullable
  default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }
    
  @Nullable
  default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }

}

위 함수들을 구현 함으로서 Bean 초기화 전/후 에 Bean 에 대한 커스텀 로직을 수행 할 수 있다.

5. Initialization 초기화

Bean 이 InitializingBean 인터페이스를 구현하는 경우 afterPropertiesSet 메서드 호출. 또는, @PostConstruct 애노테이션이 붙은 메서드를 동작시킴

package org.springframework.beans.factory;

public interface InitializingBean {

	void afterPropertiesSet() throws Exception;

}

6. BeanPostProcessor 후처리

위의 4번에서 소개한 인터페이스의 후처리 메서드가 동작한다.

7. Read for Use 사용

Bean 의 사용 준비가 완료되고 애플리케이션에서 사용될 수 있다

8. Destruction 소멸

애플리케이션 컨텍스트가 종료되면 Bean 이 소멸됨

DisposableBean 인터페이스를 구현하는 경우 destroy 메서드가 호출되며 @PreDestroy 애노테이션이 붙은 메서드가 동작


이 외에도 생명주기를 위한 여러 인터페이스를 지원한다.

아래는 org.springframework.beans.factory.BeanFactory 의 주석에 명시되어있는 Bean 의 표준 생성 라이프사이클을 표로 정리 한 것이다

인터페이스 / 기능 설명
BeanNameAware.setBeanName 빈에 Spring이 해당 빈의 이름을 설정하는 데 사용.
BeanClassLoaderAware.setBeanClassLoader 빈에 클래스 로더를 설정하여 동적으로 클래스를 로드할 수 있게 함.
BeanFactoryAware.setBeanFactory 빈에 속한 BeanFactory의 참조를 설정하여 빈이 컨테이너에서 다른 빈들을 조회할 수 있게 함.
EnvironmentAware.setEnvironment 빈에 환경 구성 속성에 접근할 수 있는 기능을 제공.
EmbeddedValueResolverAware.setEmbeddedValueResolver 빈에 문자열 값 안의 플레이스홀더를 해석하는 데 사용될 StringValueResolver를 설정.
ResourceLoaderAware.setResourceLoader (애플리케이션 컨텍스트에서만 적용) 리소스를 로드하는 데 사용할 수 있는 ResourceLoader를 빈에 설정.
ApplicationEventPublisherAware.setApplicationEventPublisher (애플리케이션 컨텍스트에서만 적용) 이벤트를 발행하는 데 사용할 ApplicationEventPublisher를 빈에 설정.
MessageSourceAware.setMessageSource (애플리케이션 컨텍스트에서만 적용) 빈에 국제화(i18n) 메시지를 처리하는 데 사용되는 MessageSource를 설정.
ApplicationContextAware.setApplicationContext (애플리케이션 컨텍스트에서만 적용) 빈에게 실행 중인 ApplicationContext에 대한 참조를 설정하여 빈이 애플리케이션 컨텍스트와 상호작용할 수 있게 설정.
ServletContextAware.setServletContext (웹 애플리케이션 컨텍스트에서만 적용) 웹 애플리케이션의 경우, ServletContext를 빈에 설정하여 빈이 서블릿 컨텍스트와 상호작용할 수 있게 함.
BeanPostProcessors.postProcessBeforeInitialization 빈 초기화 전에 커스텀 로직을 실행.
InitializingBean.afterPropertiesSet 빈에게, 모든 속성이 설정된 후에 초기화 로직을 실행하는 기능을 제공.
사용자 정의 init-method 정의 빈에 대한 사용자 정의 초기화 메서드를 지정할 수 있다.
BeanPostProcessors.postProcessAfterInitialization 빈 초기화 후에 커스텀 로직을 실행.