[빈 스코프] 빈 스코프와 프로토타입 스코프
by mignon25빈 스코프 종류
- 싱글톤 : 기본 스코프, 스프링 컨테이너의 시작과 종료까지 유지되는 가장 넓은 범위의 스코프
- 프로토 타입 : 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프
- 웹 관련 스코프
- request : 웹 요청이 들어오고 나갈 때까지 유지되는 스코프
- session : 웹 세션이 생성되고 종료될 때까지 유지되는 스코프
- application : 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프
빈 스코프 지정
// 컴포넌트 스캔 자동 등록
@Scope("prototype")
@Component
public class HellloBean {}
// 수동 등록
@Scope("prototype")
@Bean
PrototypeBean HelloBean() {
return new HelloBean();
}
프로토타입 스코프
스프링 컨테이너는 프로토타입의 빈을 생성하고, 의존관계 주입, 초기화까지만 처리한다.
- 싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환
- 프로토타입 스코프의 빈을 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환
- 클라이언트에 빈을 반환한 이후 스프링 컨테이너는 생성된 프로토타입 빈을 관리하지 않는다.
- 프로토타입 빈을 관리할 책임은 프로토타입 빈을 받은 클라이언트에 있다.
- 그래서 @PreDestroy 같은 종료 메서드가 호출되지 않는다.
< 싱글톤 스코프로 생성한 빈과 프로토타입 스코프로 생성한 빈 출력 테스트>
싱글톤 스코프 빈은 init()과 destroy() 가 모두 호출되었고, 인스턴스 주소값도 동일하다.
그러나 프로토타입 스코프 빈은 컨테이너를 종료해주었음에도 init()만 호출이 되고, 각 인스턴스 주소값도 다르다.
public class SingletonTest {
@Test
void singletonBeanFind() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class);
SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);
System.out.println("singletonBean1 = " + singletonBean1);
System.out.println("singletonBean2 = " + singletonBean2);
assertThat(singletonBean1).isSameAs(singletonBean2);
ac.close();
}
@Scope("singleton")
static class SingletonBean {
@PostConstruct
public void init() {
System.out.println("SingletonBean.init");
}
@PreDestroy
public void destroy() {
System.out.println("SingletonBean.destroy");
}
}
}
// 출력 결과
SingletonBean.init
singletonBean1 = hello.core.scope.SingletonTest$SingletonBean@5505ae1a
singletonBean2 = hello.core.scope.SingletonTest$SingletonBean@5505ae1a
16:41:19.544 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3ee37e5a, started on Fri Apr 07 16:41:19 KST 2023
SingletonBean.destroy
public class PrototypeTest {
@Test
void prototypeBeanFind() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeTest.PrototypeBean.class);
System.out.println("find prototypeBean1");
PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
System.out.println("find prototypeBean2");
PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);
System.out.println("prototypeBean1 = " + prototypeBean1);
System.out.println("prototypeBean2 = " + prototypeBean2);
assertThat(prototypeBean1).isNotSameAs(prototypeBean2);
ac.close();
}
@Scope("prototype")
@Component
static class PrototypeBean {
@PostConstruct
public void init() {
System.out.println("PrototypeBean.init");
}
@PreDestroy
public void destroy() {
System.out.println("PrototypeBean.destroy");
}
}
}
// 출력 결과
find prototypeBean1
PrototypeBean.init
find prototypeBean2
PrototypeBean.init
prototypeBean1 = hello.core.scope.PrototypeTest$PrototypeBean@545b995e
prototypeBean2 = hello.core.scope.PrototypeTest$PrototypeBean@76a2ddf3
16:43:03.200 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@3ee37e5a, started on Fri Apr 07 16:43:03 KST 2023
'Spring' 카테고리의 다른 글
| Spring MVC의 동작 방식과 구성 요소 (0) | 2023.04.14 |
|---|---|
| Spring MVC 란? (0) | 2023.04.14 |
| [AOP] Advice (0) | 2023.04.12 |
| [AOP] JoinPoint (0) | 2023.04.12 |
| [AOP] Pointcut (0) | 2023.04.12 |
블로그의 정보
Mignon'S Dev Log
mignon25