김영한의 스프링 핵심 원리(기본편) - 스프링 빈의 라이프사이클과 생명주기 콜백(@PostConstruct, @PreDestory)

2025. 2. 2. 14:01·김영한의 스프링 핵심 원리(기본편)

Question

  • 스프링 빈의 라이프사이클에 대해 설명하시오
  • 생성자 부분과 객체 초기화 부분을 분리하는 이유를 설명하시오
  • InitializingBean, DisposableBean을 활용하는 것의 단점을 설명하시오
  • @Bean initMethod, destoryMethod의 장점을 설명하시오
  • @Bean destoryMethod를 지정해주지 않으면 어떻게 동작하는가?
  • @PostConstruct, @PreDestory 방식의 장단점을 설명하시오

 

 

스프링 빈의 라이프사이클

  • 스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 사용 -> 소멸전 콜백 -> 스프링 종료
  • 초기화 콜백: 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
  • 소멸전 콜백: 빈이 소멸되기 직전에 호출
  • 객체의 생성과 초기화의 분리
    • 생성자는 필수 정보(파라미터)를 받고, 메모리를 할당해서 객체를 생성하는 책임을 가짐
    • 반면, 초기화는 생성된 값을 활용해 외부 커넥션을 연결하는 등 무거운 동작을 수행
    • 따라서, 생성자 안에서 초기화 작업까지 모두 하는게 아니라 생성자의 역할과 초기화의 역할을 나누는게 좋음
    • 만약 초기화 작업이 매우 간단한 작업이라면 생성자 안에서 하는 것도 무방함

 

스프링에서 지원하는 3가지 빈 생명주기 콜백

  • 인터페이스(InitializingBean, DisposableBean)
  • 설정 정보에 초기화 메서드, 종료 메서드 지정
  • @PostConstruct, @PreDestroy 애노테이션 지원

 

 

인터페이스 InitializingBean, DisposableBean

public class NetworkClient implements InitializingBean, DisposableBean {
    private String url;

    public NetworkClient() {
        System.out.println("생성자 호출, url = " + url);
    }

    public void setUrl(String url) {
        this.url = url;
    }

    // 서비스 시작 시 호출
    public void connect() {
        System.out.println("connect: " + url);
    }

    public void call(String message) {
        System.out.println("call: " + url + " message = " + message);
    }

    // 서비스 종료 시 호출
    public void disConnect() {
        System.out.println("close: " + url);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        connect();
        call("초기화 연결 메시지");
    }

    @Override
    public void destroy() throws Exception {
        disConnect();
    }
}
  • 위와 같은 NetworkClient라는 클래스를 스프링 빈으로 등록해서 사용하고자 할 때 초기화 콜백, 소멸전 콜백을InitializingBean, DisposableBean 인터페이스를 구현해서 적용할 수 있음.
  • 앞서 말한 스프링 빈의 라이프 사이클에 따라, 의존관계 주입 이후에 afterPropertiesSet() 함수가 자동으로 호출되고, 빈이 제거되기 직전에 destroy() 함수가 호출됨.
  • 이 인터페이스는 스프링 전용 인터페이스라, 스프링 전용 인터페이스에 의존함
  • 초기화, 소멸 메서드의 이름을 변경할 수 없음( afterPropertiesSet, destroy)
  • implement를 추가해 override를 넣어줘야 하기 때문에 내가 코드를 고칠 수 없는 외부 라이브러리에 적용 불가
  • 이 방법은 스프링 매우 초창기에 나온 방법이라 현재는 더 나은 방법들 때문에 거의 사용하지 않음.

 

빈 등록 초기화, 소멸 메서드 지정(@Bean initMethod, destoryMethod)

@Configuration
static class LifeCycleConfig {
    @Bean(initMethod = "init", destroyMethod = "close")
    public NetworkClient networkClient() {
        NetworkClient networkClient = new NetworkClient();
        networkClient.setUrl("http://hello-spring.dev");
        return networkClient;
    }
}
  • 위와 같이 Config 파일에서 빈으로 등록할 때 초기화 콜백, 소멸자 콜백 함수 명을 직접 입력해주면, 해당 콜백 메소드가 해당 시점에 불리도록 설정해줄 수 있음
  • 이전 방법과 비교하여 메서드 이름을 자유롭게 설정할 수 있음
  • 스프링 빈이 스프링 코드에 의존하지 않음
  • Bean을 등록해주는 부분에서 설정해주기 때문에 코드를 고칠 수 없는 외부 라이브러리를 사용하더라도 적용해줄 수 있음
  • destroyMethod="" 처럼 지정해주지 않은 경우 기본 값으로 (inferred)로 등록되어 있음.
    • 라이브러리는 대부분 소멸자 콜백으로 close, shutdown이라는 이름의 종료 메서드를 사용하므로, destoryMethod를 지정해주지 않으면 close, shutdown 메소드를 자동으로 호출해줌.

 

@PostConstruct, @PreDestroy

public class NetworkClient {
    private String url;

    public NetworkClient() {
        System.out.println("생성자 호출, url = " + url);
    }

    public void setUrl(String url) {
        this.url = url;
    }

    // 서비스 시작시 호출
    public void connect() {
        System.out.println("connect: " + url);
    }

    public void call(String message) {
        System.out.println("call: " + url + " message = " + message);
    }

    // 서비스 종료시 호출
    public void disConnect() {
        System.out.println("close: " + url);
    }

    @PostConstruct
    public void init() {
        System.out.println("NetworkClient.init");
        connect();
        call("초기화 연결 메시지");
    }

    @PreDestroy
    public void close() {
        System.out.println("NetworkClient.close");
        disConnect();
    }
}

 

  • 직접 초기화 콜백, 소멸자 콜백 함수를 정의해 주고 @PostConstruct, @PreDestory 어노테이션만 붙여주면 해당 시점에 불림
  • 최신 스프링에서 가장 권장하는 방법이며, 매우 편리함
  • javax 패키지라 스프링에 종속적인 방법이 아니라 자바 표준임
  • 컴포넌트 스캔과 잘 어울림
  • 유일한 단점은, 외부 라이브러리에 적용하지 못하므로 이 경우 이전의 @Bean 방법을 활용해야함

 

 

'김영한의 스프링 핵심 원리(기본편)' 카테고리의 다른 글

김영한의 스프링 핵심 원리(기본편) - 총 정리  (0) 2026.01.19
김영한의 스프링 핵심 원리(기본편) - 스프링 빈의 스코프와 Provider 그리고 Proxy  (3) 2025.02.02
김영한의 스프링 핵심 원리(기본편) - Bean 주입 방식과 Bean 중복 조회 문제  (2) 2025.02.02
김영한의 스프링 핵심 원리(기본편) - @ComponentScan과 @Autowired  (2) 2025.01.31
김영한의 스프링 핵심 원리(기본편) - 스프링의 싱글톤 패턴과 @Configuration  (1) 2025.01.31
'김영한의 스프링 핵심 원리(기본편)' 카테고리의 다른 글
  • 김영한의 스프링 핵심 원리(기본편) - 총 정리
  • 김영한의 스프링 핵심 원리(기본편) - 스프링 빈의 스코프와 Provider 그리고 Proxy
  • 김영한의 스프링 핵심 원리(기본편) - Bean 주입 방식과 Bean 중복 조회 문제
  • 김영한의 스프링 핵심 원리(기본편) - @ComponentScan과 @Autowired
5jyan5
5jyan5
  • 5jyan5
    jyan
    5jyan5
  • 전체
    오늘
    어제
    • 분류 전체보기 (242)
      • 김영한의 스프링 핵심 원리(기본편) (8)
      • 김영한의 스프링 핵심 원리 - 고급편 (11)
      • 김영한의 스프링 MVC 1편 (1)
      • 김영한의 스프링 DB 1편 (3)
      • 김영한의 스프링 MVC 2편 (3)
      • 김영한의 ORM 표준 JPA 프로그래밍(기본편) (9)
      • 김영한의 스프링 부트와 JPA 활용2 (2)
      • 김영한의 실전 자바 - 중급 1편 (1)
      • 김영한의 실전 자바 - 고급 1편 (9)
      • 김영한의 실전 자바 - 고급 2편 (9)
      • Readable Code: 읽기 좋은 코드를 작성.. (2)
      • 김영한의 실전 자바 - 고급 3편 (9)
      • CKA (118)
      • 개발 (37)
      • 경제 (4)
      • 리뷰 (1)
      • 정보 (2)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      고급
      빈 후처리기
      JPQL
      락
      Target
      @args
      단방향 맵핑
      버퍼
      cglib
      김영한
      requset scope
      log trace
      reentarantlock
      @discriminatorcolumn
      WAS
      스레드
      양방향 맵핑
      @within
      페치 조인
      조회 성능 최적화
      @discriminatorvalue
      jdk 동적 프록시
      프록시 팩토리
      hibernate5module
      Thread
      자바
      gesingleresult
      typequery
      프록시
      jpq
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.2
    5jyan5
    김영한의 스프링 핵심 원리(기본편) - 스프링 빈의 라이프사이클과 생명주기 콜백(@PostConstruct, @PreDestory)
    상단으로

    티스토리툴바