코드 그라데이션
프로토타입 스코프 본문
프로토타입 스코프
싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환한다.
반면에 프로토타입 스코프를 스프링 컨테이너에 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.
싱글톤 빈 요청
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