스프링의 IoC컨테이너는 Bean을 관리한다. 의존성을 관리해주고 객체들을 싱글톤으로 관리해주며 이번에 설명할 Bean의 생성과 소멸까지의 Lifecycle을 관리하는 역할 또한 가지고 있다.
Spring Bean의 Life Cycle은 간단하게 보면 "객체 생성 > 의존관계 주입" 순서로 이루어진다. 그렇기 때문에 의존관계 주입이 다 끝난 이후에야 우리가 사용할 테이터에 값이 채워지며 전 초기화 단계에서는 null인 상태로 존재한다.
1. Spring Bean의 Lifecycle
1. 스프링 IoC 컨테이너 생성
2. Bean 생성 : IoC컨테이너는 컴포넌트 스캔을 통해 빈을 찾아서 등록한다(@Component, @Bean.. 등). 이 과정에서 기본 생성자를 호출하여 객체를 만든다. // 생성자 주입의 경우 객체를 생성해서 넣어줘야 하기 때문에 여기서 경우적으로 일어난다.
3. 의존관계 주입 : 필드 주입, 수정자 주입의 단계에서는 여기서 의존관계가 주입된다. 네트워크 연결 같은 리소스 설정 작업이 이루어진다.
4. 초기화 콜백 메소드 호출 : 초기화 메서드를 호출하여 빈을 사용할 준비를 마친다.
5. Bean 사용 : 어플리케이션이 열심히 돌아가는 중!
6. 소멸 전 콜백 메소드 호출 : 실제로 소멸은 일어나지 않고 Bean을 소멸시키고 리소스를 해제시키는 코드들이 담긴 소멸 메서드를 호출한다.
7. 스프링 종료 : 스프링 IoC컨테이너가 종료되기 전 생성했던 객체들을 소멸시키는 과정이다. 네트워크 연결 종료와 같은 리소스를 해제하는 작업도 여기에 포함되어 있다.
2. 빈 생명주기 콜백
1. 인터페이스 구현 - InitializingBean, DisposableBean
InitializingBean : 스프링이 지원하는 초기화 메서드. 빈 생명주기에서 3번 의존관계 주입이 끝난 후 초기화를 진행한다.
DisposableBean : 스프링이 지원하는 소멸 메서드. 빈 생명주기에서 7번 스프링이 종료되기 전에 자원 해제 등을 하기위한 소멸메서드를 호출한다.
@Component
class MySpringBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() {
}
@Override
public void destroy() {
}
}
인터페이스 방식의 단점
1. 스프링이 지원하는 스프링 전용 인터페이스이기 때문에 해당 클래스가 스프링에 의존적이게 된다.
2. 인터페이스에서 지정된 초기화, 소멸 메서드를 구현하기 때문에 메서드 명을 변경할 수 없다.
3. 외부 라이브러리에 적용이 불가능하다.
스프링 초창기에 나온 방법들이고, 단점이 많기 때문에 요즘은 이 방법을 사용하지 않는다. 아래의 더 좋은 방법을 살펴보자
2. @Bean 어노테이션에 초기화, 종료 메서드 지정
@Bean 어노테이션에 옵션으로 초기화, 소멸 메서드의 이름을 지정하는 방법이다.
public class Method {
public void init() throws Exception {
// 초기화 (의존관계 주입이 끝나면 호출)
}
public void close() throws Exception {
// 소멸 (인스턴스 소멸, 연결 종료 등)
}
}
public class LifeCycle() {
@Bean(initMethod = "init", destroyMethod = "close")
public Method newMethod() {
return new SpringBean();
}
}
@Bean 어노테이션 옵션 부여 방식의 장점
1. 메서드 명을 개발자가 지정 가능하다.
2. 스프링에 의존적이지 않다.
3. 코드가 아닌 설정 정보를 사용하기 때문에 외부 라이브러리에도 초기화, 종료 메서드를 적용할 수 있다.
- 외부 라이브러리를 불러와서 사용할 경우 해당 라이브러리에 있는 메서드명을 적어주면 된다.
종료메서드 추론
@Bean의 소멸 지정 메서드인 destoryMethod의 기본값은 (inferred)로 설정되어 있기 때문에 빈에 등록된 close, shutdown라는 이름의 메서드를 자동으로 소멸 메서드로 인식하고 호출해준다. 그래서 따로 종료 메서드를 지정하지 않더라도 잘 동작한다. 만약 추론 기능을 사용하기 싫으면 destoryMethod=""로 지정해주면 된다.
3. @PostConstruct, @PreDestory 어노테이션
간단하게 초기화 메서드에는 @PostConstruct, 소멸 메서드에는 @PreDestory 어노테이션을 붙혀주면 된다.
@PostConstruct
public void init() throws Exception {
}
@PreDestroy
public void close() throws Exception {
}
@PostConstruct, @PreDestory의 장점
1. 스프링에서 공식적으로 권장하는 방식이다.
2. 자바에서 지원하는 표준 기술이기 때문에 스프링이 아닌 다른 컨테이너에서도 잘 동작한다.
3. 컴포넌트 스캔과 잘 어울린다.
4. 간편하다.
@PostConstruct, @PreDestory의 단점
1. 코드를 변경할 수 없는 외부 라이브러리에 적용이 불가능 하다.
- 외부 라이브러리는 이미 만들어져있는 코드이고 우리가 변경 불가능하기 때문에 어노테이션을 붙히지 못한다. 그래서 이 경우에는 2번 방법인 @Bean에 옵션을 주는 방법을 사용해야한다.
'Backend > Spring' 카테고리의 다른 글
[Spring/Junit5] @Test(expected = ~) Junit5에서 사용하기 (0) | 2024.01.26 |
---|---|
[Spring] 스프링 빈 중복조회 해결 방법 (1) | 2023.12.29 |
[Spring/Error][해결] 스프링 리액트 통합 빌드 - Unable to access jarfile (0) | 2023.12.25 |
[Spring/Error][해결] Spring-React 통합 빌드 오류 - An input file was expected to be present but it doesn't exist. (0) | 2023.12.25 |
[Spring/Error][해결] VSCode jdk 버전 업그레이드하기 (0) | 2023.12.25 |