728x90
✍ 빈 생명주기 콜백 지원 3가지
- 인터페이스(InitializingBean, DisposableBean)
- 설정 정보에 초기화 메서드, 종료 메서드 지정
- @PostConstruct, @PreDestroy 애노테이션 지원 (이거 사용하면 됨..)
1. 인터페이스 InitializingBean, DisposableBean (거의 사용 X)
implements InitializingBean, DisposableBean
예제
package hello.core.lifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
// ✔ implements 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);
}
// implements InitializingBean
@Override // ✔ afterPropertiesSet() 메서드로 초기화를 지원
public void afterPropertiesSet() throws Exception {
connect();
call("초기화 연결 메시지");
}
// implements DisposableBean
@Override // ✔ destroy() 메서드로 소멸을 지원
public void destroy() throws Exception {
disConnect();
}
}
implements InitializingBean : afterPropertiesSet() 메서드로 초기화를 지원
implements DisposableBean : destroy() 메서드로 소멸을 지원
테스트 코드
package hello.core.lifecycle;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class BeanLifeCycleTest {
@Test
public void LifeCycleTest() {
// close를 쓰기 위해 ConfigurableApplicationContext
ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
LifeCycleConfig client = ac.getBean(LifeCycleConfig.class);
ac.close();
}
@Configuration
static class LifeCycleConfig {
@Bean
public NetworkClient networkClient() {
NetworkClient networkClient = new NetworkClient();
networkClient.setUrl("http://hello-spring.dev");
return networkClient;
}
}
}
초기화, 소멸 인터페이스 단점
- 이 인터페이스는 스프링 전용 인터페이스다. 해당 코드가 스프링 전용 인터페이스에 의존한다.
- 초기화, 소멸 메서드의 이름을 변경할 수 없다. afterPropertiesSet(), destroy() 메서드 이름이 고정이다.
- 내가 코드를 고칠 수 없는 외부 라이브러리에 적용할 수 없다.
2. 빈 등록 초기화, 소멸 메서드 지정
설정 정보에 @Bean(initMethod = "init", destroyMethod = "close") 처럼 초기화, 소멸 메서드를 지 정할 수 있다.
초기화, 소멸 인터페이스에서는 afterPropertiesSet(), destroy() 로 메서드 이름이 고정되어 있지만,
설정 정보에 초기화 메서드, 종료 메서드 지정은 메서드 이름 지정이 가능하다.
설정 정보를 사용하도록 변경
package hello.core.lifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
// ✔ implements 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);
}
// ✔ 메소드 이름 변경 가능
public void init() { // 초기화
System.out.println("NetworkClient.init");
connect();
call("초기화 연결 메시지");
}
public void close() { // 소멸
System.out.println("NetworkClient.close");
disConnect();
}
}
설정 정보에 초기화 소멸 메서드 지정(테스트 코드)
@Bean(initMethod = "init", destroyMethod = "close")
위에서 만들어둔 초기화, 소멸 메서드 이름을 넣어준다.
package hello.core.lifecycle;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public class BeanLifeCycleTest {
@Test
public void LifeCycleTest() {
// close를 쓰기 위해 ConfigurableApplicationContext
ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
LifeCycleConfig client = ac.getBean(LifeCycleConfig.class);
ac.close();
}
@Configuration
static class LifeCycleConfig {
// ✔ 여기서 메서드 지정
// ✔ 지정해준 메서드 이름을 넣어주면 된다.
// ✔ 소멸 메서드 이름이 close, shutdown이라면 생략 가능하다.
@Bean(initMethod = "init", destroyMethod = "close")
public NetworkClient networkClient() {
NetworkClient networkClient = new NetworkClient();
networkClient.setUrl("http://hello-spring.dev");
return networkClient;
}
}
}
설정 정보 사용 특징
- 메서드 이름을 자유롭게 줄 수 있다.
- 스프링 빈이 스프링 코드에 의존하지 않는다.(imprements는 사용하지 않는다는 말)
- 코드가 아니라 설정 정보를 사용하기 때문에 코드를 고칠 수 없는 외부 라이브러리에도 초기화, 종료 메서드를 적용할 수 있다.
종료 메서드 추론
- @Bean의 destroyMethod 속성에는 아주 특별한 기능이 있다.
- 라이브러리는 대부분 close , shutdown 이라는 이름의 종료 메서드를 사용한다.
- @Bean의 destroyMethod 는 기본값이 (inferred) (추론)으로 등록되어 있다.
- 이 추론 기능(inferred)은 close , shutdown 라는 이름의 메서드를 자동으로 호출해준다.
- 이름 그대로 종료 메서드를 추론해서 호출해준다.
- 따라서 직접 스프링 빈으로 등록하면 종료 메서드는 따로 적어주지 않아도 잘 동작한다.
- 추론 기능을 사용하기 싫으면 destroyMethod="" 처럼 빈 공백을 지정하면 된다.
3. (✔ 이거 사용!) 애노테이션 @PostConstruct, @PreDestroy
package hello.core.lifecycle;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
// ✔ implements 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);
}
@PostConstruct // ✔ 초기화 애노테이션
public void init() {
System.out.println("NetworkClient.init");
connect();
call("초기화 연결 메시지");
}
@PreDestroy // ✔ 소멸 애노테이션
public void close() {
System.out.println("NetworkClient.close");
disConnect();
}
}
테스트코드
@Configuration
static class LifeCycleConfig {
@Bean
public NetworkClient networkClient() {
NetworkClient networkClient = new NetworkClient();
networkClient.setUrl("http://hello-spring.dev");
return networkClient;
}
}
@PostConstruct, @PreDestroy 애노테이션 특징
- 최신 스프링에서 가장 권장하는 방법이다.
- 애노테이션 하나만 붙이면 되므로 매우 편리하다.
- 패키지를 잘 보면 javax.annotation.PostConstruct 이다. 스프링에 종속적인 기술이 아니라 JSR-250 라는 자바 표준이다. 따라서 스프링이 아닌 다른 컨테이너에서도 동작한다.
- 컴포넌트 스캔과 잘 어울린다.
단점
외부 라이브러리에는 적용하지 못한다는 것이다. 외부 라이브러리를 초기화, 종료 해야 하면 @Bean(initMethod = "init", destroyMethod = "close") 의 기능을 사용하자.
정리
- @PostConstruct, @PreDestroy 애노테이션을 사용
- 코드를 고칠 수 없는 외부 라이브러리를 초기화, 종료해야 하면 @Bean 의 initMethod , destroyMethod 를 사용하자
'공부 > Spring' 카테고리의 다른 글
[Spring] 빈 스코프 - 프로토타입 스코프와 싱글톤 빈과 함께 사용시 문제점 (0) | 2024.01.02 |
---|---|
[Spring] 빈 스코프 - 빈 스코프(싱글톤 스코프, 프로토타입 스코프) (1) | 2023.12.31 |
[Spring] 빈 생명주기 콜백 - 빈 생명주기 콜백 시작(스프링 빈 라이프사이클) (1) | 2023.12.31 |
[Spring] 자동 빈, 수동 빈의 올바른 실무 운영 기준(언제 자동빈, 수동빈 사용할까?) (1) | 2023.12.31 |
[Spring] 조회한 빈이 모두 필요할 때, List, Map (1) | 2023.12.30 |