빈 라이프사이클

@MinSang · October 27, 2024 · 6 min read

0. 클래스 식별

Spring 컨테이너가 애플리케이션을 시작할 때, 먼저 클래스패스를 스캔하여 @Configuration, @Component, @Bean과 같은 어노테이션이 붙은 클래스를 찾아서 등록합니다. 이 과정에서 @ComponentScan을 사용해 패키지 범위를 설정할 수도 있고, 해당 어노테이션을 통해 애플리케이션 내에서 사용할 빈을 탐색하게 됩니다. 이 과정은 리플렉션을 통해 수행됩니다.

1. 빈 정의(Bean Definition)

Spring은 BeanDefinition 객체를 사용해 빈의 정보(클래스, 스코프, 의존성 등)를 정의합니다. 여기서 싱글톤인지, 프로토타입인지 같은 스코프가 설정되고, 해당 빈의 초기화/소멸 메서드(init-method, destroy-method)도 함께 정의됩니다. 이때, BeanFactoryPostProcessor와 같은 후처리기를 통해 정의된 빈을 추가적으로 수정하거나, 컨테이너가 어떤 빈을 등록할지 결정할 수도 있습니다.

2. 빈 인스턴스화(Bean Instantiation)

이제 본격적으로 빈을 인스턴스화하는 단계입니다. 여기서는 미리 정의된 빈 정보를 바탕으로 빈을 생성하는데, 싱글톤이면 이미 생성된 빈을 반환하고, FactoryBean이면 그 팩토리가 실제 객체를 생성하게 됩니다. 동시에 Lazy-loading 설정 여부도 확인해서, 필요할 때만 로드되는 빈을 다르게 처리합니다.

3. 의존성 주입(Dependency Injection)

의존성 주입은 크게 생성자 주입수정자(setter) 주입으로 나눌 수 있습니다. 생성자 주입은 빈을 생성할 때 바로 의존성을 주입하는 방식이고, 수정자 주입은 객체가 먼저 생성된 후 나중에 의존성을 주입하는 방식입니다. 주의할 점은, Spring은 이 단계에서 순환 의존성(Circular Dependency) 문제를 해결하려고 합니다. 순환 참조가 발생하면, Spring이 이를 해결할 수 있도록 프로토타입 스코프 빈을 조정하거나 프록시를 생성하는 방식으로 처리합니다.

4. 빈 후처리기 전달(BeanPostProcessor)

Spring은 빈을 인스턴스화한 뒤, 이를 빈 저장소에 등록하기 전에 빈 후처리기(BeanPostProcessor)에 전달합니다. 이때 후처리기는 빈이 초기화되기 전(beforeInitialization)후(afterInitialization) 단계에서 작업을 수행할 수 있습니다. 주로 AOP(Aspect-Oriented Programming)나 프록시 생성, 커스텀 로직 적용이 이 단계에서 이루어집니다.

5. 프록시 적용 및 어드바이저 작업

Spring AOP가 적용될 대상인 빈은, Advisor에서 제공하는 포인트컷(Pointcut)에 의해 선택됩니다. 포인트컷 조건에 맞는 빈이 프록시 대상이라면, CGLIB 또는 JDK 동적 프록시를 사용해 프록시 객체를 생성합니다. 이 프록시 객체는 원래 빈을 대신하여 메서드를 호출할 때 가로채기 기능을 수행합니다. 프록시가 생성된 빈은 빈 저장소에 등록됩니다.

6. 초기화 콜백 메서드 호출

Spring은 이 과정에서 빈의 라이프사이클 콜백을 호출합니다. @PostConstruct 어노테이션이 붙은 메서드나 InitializingBean 인터페이스의 afterPropertiesSet() 메서드가 이때 호출됩니다. 이 메서드들은 빈이 완전히 초기화된 후에 특정 초기화 작업을 수행하는 데 사용됩니다.

7. 빈 사용

이제 모든 의존성 주입이 완료된 후, 애플리케이션에서 해당 빈을 실제로 사용하게 됩니다. Spring 컨테이너는 애플리케이션 내에서 필요한 곳에 빈을 주입하여 비즈니스 로직이 실행되도록 합니다.

8. 소멸 전 콜백 메서드 호출

애플리케이션이 종료되거나, 빈의 생명주기가 끝날 때, Spring은 빈의 소멸 콜백을 호출합니다. 이는 @PreDestroy 어노테이션이 붙은 메서드나 DisposableBean 인터페이스의 destroy() 메서드로 처리됩니다. 이 단계에서는 주로 파일 닫기, DB 연결 종료 등 자원을 정리하는 작업이 수행됩니다.

9. 스프링 종료 및 리소스 해제

애플리케이션 컨텍스트가 종료되면, Spring 컨테이너는 남아 있는 빈을 모두 소멸시키고, 관련된 모든 자원(예: 캐시, 파일 핸들 등)을 해제합니다. 이때 각 빈에 정의된 소멸 메서드들이 올바르게 호출되었는지 확인하고, 필요시 후처리기를 다시 호출하여 리소스 정리를 보조할 수 있습니다.

Reference

spring docs

@MinSang
지식과 경험을 기록하는 TIL 저장소