![[스프링 핵심 원리 - 기본편] 8. 빈 생명주기 콜백](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDOr2z%2FbtsCSdu8iX3%2F2hZhuSkhVsPrJjPqCYBic0%2Fimg.png)
인프런 김영한 강사님의 스프링 핵심 원리 - 기본편을 수강하고 정리한 글입니다.
스프링 핵심 원리 - 기본편 - 인프런 | 강의
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 📢
www.inflearn.com
📌 빈 생명주기 콜백 시작
✅ 스프링 빈 라이프사이클
생성자 주입을 제외한 다른 의존 주입 방법 : 객체 생성 ==> 의존관계 주입
스프링 빈은 객체를 생성하고 의존관계 주입이 모두 끝난 다음에야 필요한 데이터를 사용할 수 있다.
그런데 개발자가 이 시점을 어떻게 알 수 있을까?
스프링은 의존관계 주입이 완료되면 스프링 빈에게 콜백 메서드를 통해서 초기화 시점을 알려준다.
또한, 스프링은 스프링 컨테이너가 종료되기 직전에 소멸 콜백을 제공하여 안전한 종료 작업 진행을 돕는다.
✅ 싱글턴 스코프 스프링 빈의 이벤트 라이프사이클
1. 스프링 컨테이너 생성
2. 스프링 빈 생성 (생성자 주입 방식 사용 시 이 단계에서 의존관계를 주입한다.)
3. 의존관계 주입(수정자 주입, 필드 주입)
4. 초기화 콜백
5. 사용
6. 소멸 전 콜백
7. 스프링 종료
여기서 초기화 콜백은 스프링 빈이 생성되고 빈의 의존관계 주입이 완료된 이후에 호출되며,
소멸 전 콜백은 스프링 빈이 소멸되기 직전에 호출된다.
✅ 스프링이 빈 생명주기 콜백을 지원하는 3가지 방법
1. 인터페이스 (InitializingBean, DisposableBean)
2. 설정 정보에 초기화 메서드, 종료 메서드 지정
3. @PostConstruct, @PreDestory 어노테이션 지원
✅ InitializingBean, DisposableBean 인터페이스
InitializingBean의 경우, afterPropertiesSet() 메서드를 오버라이딩 한다.
메서드의 초기화를 지원하며, connect() 메서드가 내장되어있다.
DisposableBean의 경우, destory() 메서드를 오버라이딩 한다.
메서드의 소멸을 지원하며, disconnect() 메서드가 내장되어 있다.
package hello.core.lifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
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();
}
}
출력 결과는 아래와 같다.
생성자 호출, url = null
NetworkClient.afterPropertiesSet
connect: http://hello-spring.dev
call: http://hello-spring.dev message = 초기화 연결 메시지
13:24:49.043 [main] DEBUG
org.springframework.context.annotation.AnnotationConfigApplicationContext -
Closing NetworkClient.destroy
close + http://hello-spring.dev
의존관계 주입 이후 초기화 메서드가 적절히 호출되었으며, 스프링 컨테이너 종료 후 소멸 메서드가 호출되었다.
✅ InitializingBean, DisposableBean의 단점
스프링 전용 인터페이스로, 코드가 스프링에 의존하게 된다.
초기화, 소멸 메서드의 이름을 변경할 수 없다.
코드를 고칠 수 없는 외부 라이브러리에는 적용할 수 없다.
이보다 좋은 방법이 많이 생겨서 사용하지 않는 케이스
✅ 빈 등록 초기화 메서드, 소멸 메서드
설정 정보에 @Bean(initMethod = "init", destoryMethod = "close") 와 같은 형식으로 초기화 메서드와 소멸 메서드를 직접 지정할 수 있다.
@Configuration
static class LifeCycleConfig {
@Bean(initMethod = "init", destroyMethod = "close")
public NetworkClient networkClient() {
NetworkClient networkClient = new NetworkClient();
networkClient.setUrl("http://hello-spring.dev");
return networkClient;
}
}
해당 방식은 메서드 이름을 자유롭게 정할 수 있으며, 스프링 빈이 스프링에 의존하지 않으면서, 코드 수정이 불가능한 외부 라이브러리에도 초기화 메서드와 종료 메서드를 적용할 수 있다.
✅ 소멸 메서드의 추론 기능
@Bean의 destoryMethod에는 특별한 기능이 있는데, close, shutdown과 같은 이름의 메서드를 자동 추론하여 호출한다.
따라서 설정 정보로 따로 적어주지 않아도 잘 동작한다.
추론 기능을 사용하기 싫다면, destoryMethod = "" 와 같이 빈 문자열 처리를 해주면 된다.
✅ @PostConstruct, @PreDestory 어노테이션
package hello.core.lifecycle;
import javax.annotation.PostConstruct;
import javax.annotation.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 : 종료 메서드로 지정
현재는 이 방식이 가장 편리하고 많이 쓰인다.
어노테이션 하나만 붙이면 되니, 매우 편리하고, 컴포넌트 스캔과도 잘 어울린다.
다만, 외부 라이브러리에 적용할 수 없다.
만약 외부 라이브러리에 적용하고 싶다면, @Bean의 initMethod, destoryMethod 속성 기능을 사용해야 한다.
'Backend > Spring' 카테고리의 다른 글
[스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술] 1. 웹 어플리케이션 이해 (0) | 2024.01.24 |
---|---|
[스프링 핵심 원리 - 기본편] 9. 빈 스코프 (0) | 2024.01.02 |
[스프링 핵심 원리 - 기본편] 7. 의존관계 자동 주입 (1) | 2024.01.02 |
[스프링 핵심 원리 - 기본편] 6. 컴포넌트 스캔 (0) | 2024.01.02 |
[스프링 핵심 원리 - 기본편] 5. 싱글톤 컨테이너 (1) | 2024.01.01 |
개발자가 되고 싶어요.