일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- kafka
- bean
- consumer
- AWS
- centos7
- spring
- CodePipeline
- git
- cd
- producer
- API
- PAGING
- Entity
- entity graph
- JPA
- Spring Data JPA
- K8s
- QueryDSL
- Kotlin
- spring kafka
- ECS
- mirror maker2
- mysql
- Streams
- transactionaleventlistener
- Kubernetes
- CI
- offsetdatetime
- topic생성
- Spring JPA
- Today
- Total
Yebali
Spring Bean의 생명주기 본문
Bean이란?
Bean이란 Spring IoC 컨테이너가 생성하고 관리하는 자바 객체를 말한다.
흔히 Java에서 new 연산자로 객체를 생성했을 때 만들어지는 객체는 빈이 아니다.
Spring Framework를 사용할 때 Spring Bean을 얻기 위해서는 ApplicationContext.getBean()와 같은 메서드를 통해 Bean을 얻을 수 있다.
Bean의 생명주기
Spring에서 관리하는 Bean들은 아래와 같은 생명주기를 가진다.
Spring 시작 -> Spring 컨테이너 생성 -> Spring Bean생성 -> 의존관계 주입 -> 초기화 콜백
-> Bean 사용 -> 소멸 전 콜백 -> 스프링 종료
Spring Bean은 객체 생성과 의존관계 주입이 끝나야 사용할 준비가 완료된다.
따라서 초기화 작업은 의존관계 주입 후 호출된다.
Spring은 Bean을 사용 전, 후 Bean에 대해 특정 작업을 하고 싶을 때
의존관계가 주입된 직후, 또는 Bean이 소멸하기 전 시점을 알 수 있도록 '초기화 콜백'과 '소멸 전 콜백'을 제공한다.
해당 콜백을 사용하는 방법 3가지를 알아보자.
1. InitializingBean, DisposableBean 인터페이스
public class BeanLifeCycleTest {
@Test
public void lifecycle() {
ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
TestBean bean = ac.getBean(TestBean.class);
ac.close();
}
@Configuration
static class LifeCycleConfig {
@Bean
public TestBean networkClient() {
TestBean testBean = new TestBean();
return testBean;
}
}
}
public class TestBean implements InitializingBean, DisposableBean {
public TestBean() {}
// 서비스 시작 시 호출
public void whenServiceStart() {
System.out.println("TestBean.whenServiceStart");
}
//서비스 종료 시 호출
public void whenServiceDone() {
System.out.println("TestBean.whenServiceDone");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("TestBean.afterPropertiesSet");
whenServiceStart();
}
@Override
public void destroy() throws Exception {
System.out.println("TestBean.destroy");
whenServiceDone();
}
}
InitializingBean, DisposableBean인터페이스의 afterPropertiesSet, destroy 메서드를 구현하여 각각 초기화 콜백, 소멸 전 콜백을 사용할 수 있다.
스프링 전용 인터페이스라 스프링에 의존하며 메서드 이름을 변경할 수 없으며 외부 라이브러리에 적용할 수 없다
지금은 거의 사용하지 않는 방식이다.
2. Bean의 설정 정보에 초기화, 종료 메서드 지정
public class BeanLifeCycleTest {
@Test
public void lifecycle() {
ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
TestBean bean = ac.getBean(TestBean.class);
ac.close();
}
@Configuration
static class LifeCycleConfig {
@Bean(initMethod = "init", destroyMethod = "close")
public TestBean networkClient() {
TestBean testBean = new TestBean();
return testBean;
}
}
}
public class TestBean {
public TestBean() {}
// 서비스 시작 시 호출
public void whenServiceStart() {
System.out.println("TestBean.whenServiceStart");
}
//서비스 종료 시 호출
public void whenServiceDone() {
System.out.println("TestBean.whenServiceDone");
}
public void init() {
System.out.println("TestBean.init");
whenServiceStart();
}
public void close() {
System.out.println("TestBean.close");
whenServiceDone();
}
}
@Bean 애너테이션의 'initMethod', 'destroyMethod' 옵션에 초기화 콜백, 소멸 전 콜백에 사용할 메서드를 명시해준다.
명시되는 메서드 명은 TestBean에 있는 메서드 이름이다.
명시된 메서드를 통해 초기화 콜백, 소멸 전 콜백을 사용할 수 있으며 메서드 명을 자유롭게 지정할 수 있고 스프링에 의존적이지도 않다.
+ 외부 라이브러리에도 적용할 수 있다.
@Bean의 distroyMethod는 추론 기능을 제공하기 때문에 흔히 사용되는 'close()', 'shutdown()'를 메서드 명으로 사용하면 개발자가 'destroyMethod'에 명시하지 않아도 해당 메서드를 소멸 전 콜백에 사용한다.
3. @PostConstruct, @PreDestory
public class BeanLifeCycleTest {
@Test
public void lifecycle() {
ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
TestBean bean = ac.getBean(TestBean.class);
ac.close();
}
@Configuration
static class LifeCycleConfig {
@Bean
public TestBean networkClient() {
TestBean testBean = new TestBean();
return testBean;
}
}
}
public class TestBean {
public TestBean() {}
// 서비스 시작 시 호출
public void whenServiceStart() {
System.out.println("TestBean.whenServiceStart");
}
//서비스 종료 시 호출
public void whenServiceDone() {
System.out.println("TestBean.whenServiceDone");
}
@PostConstruct
public void init() {
System.out.println("TestBean.init");
whenServiceStart();
}
@PreDestroy
public void close() {
System.out.println("TestBean.close");
whenServiceDone();
}
}
TestBean클래스 내부에 @PostConstruct, @PreDestory 어노테이션을 사용하여 해당 메서드를 초기화 콜백, 소멸 전 콜백에 사용한다.
스프링에서 가장 권장하는 방법이며, 사용이 간단하다.
'javax.annotation'을 사용하기 때문에 스프링에 종속적이지 않은 자바 표준이다.
단, 외부 라이브러리에 적용하지 못한다.
정리
일반적으로 @PostConstruct, @PreDestory을 사용하는 것이 가장 좋다.
코드를 고칠 수 없는 외부 라이브러리를 사용한다면 @Bean의 initMethod, destroyMethod을 사용하면 된다.
참고 : 객채 생성과 초기화는 분리하자.
생성자는 필수 정보(파라미터)를 받고 메로리를 할당해서 객체를 생성하는 일을 한다.
반면에 초기화는 생성된 값들을 활용해서 외부 커넥션을 연결하는 등 무거운 동작을 수행한다.
따라서 생성자가 하는 일과 초기화 작업을 하는 것을 분리하는 것이 유지보수 관점에서 좋다.
'Spring' 카테고리의 다른 글
Spring을 이용한 API개발 - 기본 (0) | 2021.10.11 |
---|---|
Spring JPA 준영속 엔티티 수정하기 (0) | 2021.10.11 |
Spring JPA Entity 설계 시 주의점 (0) | 2021.10.11 |
Spring JPA 1:N 관계 설정 (0) | 2021.10.10 |
Spring Bean 등록/설정 방법 (0) | 2021.10.04 |