티스토리 뷰
프로토타입 스코프
싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환한다.
반면에 프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.
싱글톤 빈 요청
1. 싱글톤 스코프의 빈을 스프링 컨테이너에 요청한다.
2. 스프링 컨테이너는 본인이 관리하는 스프링 빈을 반환한다.
3. 이후에 스프링 컨테이너에 같은 요청이 와도 같은 객체 인스턴스의 스프링 빈을 반환한다.
프로토타입 빈 요청 1
1. 프로토타입 스코프의 빈을 스프링 컨테이너에 요청한다.
2. 스프링 컨테이너는 이 시점에 프로토타입 빈을 생성하고, 필요한 의존관계를 주입한다.
프로토타입 빈 요청2
3. 스프링 컨테이너는 생성한 프로토타입 빈을 클라이언트에 반환한다.
4. 이후에 스프링 컨테이너에 같은 요청이 오면 항상 새로운 프로토타입 빈을 생성해서 반환한다.
정리
코드로 확인해보면
싱글톤 스코프 빈 테스트
package inflearn.spring_core.scope;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import static org.assertj.core.api.Assertions.assertThat;
public class SingletonTest {
@Test
public void singletonBeanFind() {
// SingletonBean 클래스 구성을 기반으로 스프링 애플리케이션 컨텍스트를 생성합니다.
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class);
// 스프링 컨테이너에서 SingletonBean의 두 인스턴스를 가져옵니다.
SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);
// singletonBean1과 singletonBean2의 참조를 출력합니다.
System.out.println("singletonBean1 = " + singletonBean1);
System.out.println("singletonBean2 = " + singletonBean2);
// 두 참조가 동일한 객체를 가리키는지 확인하여 싱글톤 범위를 확인합니다.
assertThat(singletonBean1).isSameAs(singletonBean2);
// 스프링 애플리케이션 컨텍스트를 닫습니다. 이로써 PreDestroy 메서드가 호출됩니다.
ac.close(); // 종료 (컨텍스트 종료)
}
@Scope("singleton")
static class SingletonBean {
// @PostConstruct로 주석이 달린 메서드는 빈 초기화 이후에 호출됩니다.
@PostConstruct
public void init() {
System.out.println("SingletonBean.init");
}
// @PreDestroy로 주석이 달린 메서드는 빈 파괴 이전에 호출됩니다.
@PreDestroy
public void destroy() {
System.out.println("SingletonBean.destroy");
}
}
}
실행 결과
- 빈 초기화 메서드를 실행하고,
- 같은 인스턴스의 빈을 조회하고,
- 종료 메서드까지 정상 호출 된 것을 확인할 수 있다.
프로토타입 스코프 빈 테스트
package inflearn.spring_core.scope;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import static org.assertj.core.api.Assertions.assertThat;
public class PrototypeTest {
@Test
public void prototypeBeanFind() {
// 프로토타입 빈을 사용하는 스프링 애플리케이션 컨텍스트를 생성합니다.
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
System.out.println("프로토타입 빈 1 찾기");
// 스프링 컨테이너에서 PrototypeBean의 첫 번째 인스턴스를 가져옵니다.
PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
System.out.println("프로토타입 빈 2 찾기");
// 스프링 컨테이너에서 PrototypeBean의 두 번째 인스턴스를 가져옵니다.
PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);
System.out.println("prototypeBean1 = " + prototypeBean1);
System.out.println("prototypeBean2 = " + prototypeBean2);
// 두 참조가 서로 다른 객체를 가리키는지 확인하여 프로토타입 범위를 확인합니다.
assertThat(prototypeBean1).isNotSameAs(prototypeBean2);
// 스프링 애플리케이션 컨텍스트를 닫습니다. 이로써 PreDestroy 메서드가 호출됩니다.
ac.close(); // 종료
}
@Scope("prototype")
static class PrototypeBean {
// @PostConstruct로 주석이 달린 메서드는 빈 초기화 이후에 호출됩니다.
@PostConstruct
public void init() {
System.out.println("PrototypeBean.init");
}
// @PreDestroy로 주석이 달린 메서드는 빈 파괴 이전에 호출됩니다.
@PreDestroy
public void destroy() {
System.out.println("PrototypeBean.destroy");
}
}
}
부연
실행 결과
프로토타입 빈의 특징 정리
- 스프링 컨테이너에 요청할 때 마다 새로 생성된다.
- 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입 그리고 초기화까지만 관여한다.
- 종료 메서드가 호출되지 않는다.
- 그래서 프로토타입 빈은 프로토타입 빈을 조회한 클라이언트가 관리해야 한다. 종료 메서드에 대한 호출도 클라이언트가 직접 해야한다.
728x90
반응형
'[개발] - Spring > 핵심 원리 구현' 카테고리의 다른 글
프로토타입 스코프 - 싱글톤 빈과 함께 사용시 Provider로 문제 해결 (0) | 2024.02.15 |
---|---|
프로토타입 스코프 - 싱글톤 빈과 함께 사용 시 문제점 (0) | 2024.02.15 |
빈 스코프란? (0) | 2024.02.13 |
[중간점검] 객체의 생성과 객체의 초기화 분리 (0) | 2024.02.12 |
[중간점검] 생성자 주입, 그리고 수정자 주입 (0) | 2024.02.12 |
Comments