Spring/Spring

[Spring][Core] 2-8. Bean: Customizing the Nature of a Bean

noahkim_ 2023. 10. 14. 23:51

1. Lifecycle Callbacks

  • Spring은 빈의 생명주기와 상호작용할 수 있는 여러 방법을 제공합니다.
  • 이러한 도구를 활용하여 빈의 초기화 및 파괴 과정에 사용자 지정 동작을 추가할 수 있습니다.

 

BeanPostProcessor 인터페이스

  • 빈 생성 전/후에 사용자 정의 로직을 실행할 수 있도록 하는 빈 후처리 인터페이스
  • 내부적으로 콜백 인터페이스를 찾아 적절한 메서드를 호출하기 위해 사용합니다.
  • 주요 메서드: postProcessBeforeInitialization(), postProcessAfterInitialization()

 

Initialization Callbacks

  • 초기화 메서드는 컨테이너의 싱글톤 생성 잠금 내에서 실행됩니다.
  • 여러 스레드가 동시에 호출하려는 시도를 방지합니다.

 

항목 / 방법 InitializingBean 인터페이스 @PostConstruct
init-method (XML)
설명 afterPropertiesSet() 메서드로 초기화 수행 표준 어노테이션 사용
XML의 init-method 속성 지정
✅ 장점 - 단순하고 명확
- 의존성 주입 이후 보장
- 가장 권장됨
- 가독성 우수
- Spring 비종속
- 설정 분리 가능
- 코드에 어노테이션/인터페이스 없음
❌ 단점 - Spring 종속적
- 테스트 불편
- Java 9 이상 설정 필요
- 프록시 시 주의 필요
- XML 유지보수 필요
- 메서드명 일치 주의
💡 사용 사례 코드 기반 초기화가 필요한 경우 표준 어노테이션 기반 초기화가 필요한 경우
설정 파일로 빈을 정의하는 경우

 

예시) InitializingBean 인터페이스

더보기
public class AnotherExampleBean implements InitializingBean {

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

 

예시) @PreConstruct (JSR-250)

더보기
@Component
public class BookService {

    private List<Book> books;

    @PreConstruct
    public void initialize() {
        // 빈 초기화 로직
        books = new ArrayList<>();
        books.add(new Book("Spring in Action"));
        books.add(new Book("Effective Java"));
        System.out.println("BookService initialized!");
    }
}

 

예시) init-method (xml)

더보기
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean {

    public void init() {
        // do some initialization work
    }
}

 

Destruction Callbacks

예시) DisposableBean

더보기
public class AnotherExampleBean implements DisposableBean {

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

 

예시) @PostDestroy (JSR-250)

더보기
@Component
public class DatabaseConnectionService {

    private Connection connection;

    @PostDestroy
    public void cleanup() {
        // 연결 해제 로직
        if (connection != null) {
            connection.close();
            System.out.println("Database connection closed!");
        }
    }
}

 

예시) destroy-method (xml)

더보기
<bean id="exampleDestructionBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean {

    public void cleanup() {
        // do some destruction work (like releasing pooled connections)
    }
}

   

2. Startup and Shutdown Callbacks

항목 Lifecycle LifecycleProcessor Phased SmartLifecycle
설명 빈의 생명주기를 관리 Lifecycle 확장
이벤트 반응 (refresh/close)
시작/종료의 우선순위 지정용 
Lifecycle + Phased 확장
자동 시작/비동기 종료 기능 
사용 목적 간단한 수명 주기 관리 컨텍스트 리프레시와 종료에 반응 순서 기반 시작/종료 
자동 시작과 정교한 비동기 종료 처리 필요 시 사용

 

예시) Lifecycle 인터페이스

더보기
public interface Lifecycle {
    void start();
    void stop();
    boolean isRunning();
}
메서드 설명
start() 빈이 시작될 때 실행할 로직 정의
stop() 빈이 종료될 때 실행할 로직 정의
isRunning() 현재 빈이 실행 중인지 여부 반환 (true/false)

 

예시) LifecycleProcessor

더보기
public interface LifecycleProcessor extends Lifecycle {
    void onRefresh();
    void onClose();
}
메서드 설명
onRefresh() ApplicationContext가 새로 고쳐질 때 호출됨
onClose() ApplicationContext가 닫힐 때 호출됨

 

예시) Phased

더보기
public interface Phased {
    int getPhase();	
}
메서드 설명
getPhase() 시작/종료 시 우선순위를 정의 (낮을수록 우선)

 

예시) SmartLifecycle

더보기
public interface SmartLifecycle extends Lifecycle, Phased {
    boolean isAutoStartup();
    void stop(Runnable callback);
}

 

메서드 설명
isAutoStartup() 객체가 자동으로 시작되어야 하는지 여부 (true시, start() 자동 실행)
stop(Runnable callback) 비동기 종료 처리용
종료 완료 후 callback의 run() 호출

 

3. Shutting Down the Spring IoC Container Gracefully in Non-Web Applications

  • Spring IoC 컨테이너를 웹이 아닌 애플리케이션에서 사용할 때의 안전한 종료 방법
  • 종료 후크를 등록함으로써 시스템이 안전하게 종료됩니다.
    • 싱글톤 빈에 정의된 destroy 메서드들이 호출되어 모든 리소스가 정상적으로 해제됩니다.
  • 만약 웹 환경에서 Spring의 IoC 컨테이너를 사용한다면 JVM에 종료 후크(shutdown hook)를 등록해야 합니다.

 

예시

더보기
public final class Boot {
    public static void main(final String[] args) throws Exception {
        ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");

        // add a shutdown hook for the above context...
        ctx.registerShutdownHook();

        // app runs here...
        // main method exits, hook is called prior to the app shutting down...
    }
}
  • ConfigurableApplicationContext 인터페이스에 정의된 registerShutdownHook() 메서드를 호출합니다.

 

빈의 인터페이스

항목 ApplicationContextAware
BeanNameAware
목적 자신을 생성한 ApplicationContext의 참조를 제공받기 위함
빈 이름을 얻고자 할 때
호출 시점 모든 의존성 주입 후, 초기화 콜백 전에 호출
일반 속성 주입 이후, 초기화 콜백 전에 호출
주요 사용 예 다른 빈에 접근하거나, 컨텍스트 정보를 활용할 때
자신의 이름을 로깅하거나, 조건 분기로 사용할 때

 

출처