– 빈 공간
범위: Bean이 존재할 수 있는 범위입니다.
– Spring이 지원하는 분야
원링, 프로토타입
-웹 관련 분야
요청: 들어오고 나가는 웹 요청에 의해 유지되는 영역.
session: 웹 세션이 생성되고 종료될 때까지 유지되는 범위
응용 프로그램: 웹의 서블릿 컨텍스트와 동일한 범위로 유지되는 범위
-싱글톤, 프로토타입 차이
싱글톤 빈의 경우 스프링 컨테이너는 사용자가 빈을 가져올 때 항상 같은 인스턴스의 빈을 반환하지만 사용자가 프로토타입 범위에서 빈을 가져올 때 스프링 컨테이너는 항상 새 인스턴스를 생성하고 종속성 주입 및 – 초기화만 처리합니다. 클라이언트가 반환되고 더 이상 Spring 컨테이너에 의해 관리되지 않습니다. 따라서 @Predestroy와 같은 종료 메서드는 호출되지 않습니다.
-테스트 프로토타입 스코프 빈
package hello.core.scope;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;
public class PrototypeTest {
@Test
void prototypeBeanFind(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(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);
Assertions.assertThat(prototypeBean1).isNotSameAs(prototypeBean2);
ac.close();
}
@Scope("prototype")
static class PrototypeBean{
@PostConstruct
public void init(){
System.out.println("PrototypeBean.init");
}
@PreDestroy
public void destory(){
System.out.println("PrototypeBean.destroy");
}
}
}
-prototype scope – 싱글톤 bean과 함께 사용할 때의 문제
package hello.core.scope;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;
public class SingletonWithPrototypeTest1 {
@Test
void prototypeFind(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
prototypeBean1.addCount();
Assertions.assertThat(prototypeBean1.getCount()).isEqualTo(1);
PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);
prototypeBean2.addCount();
Assertions.assertThat(prototypeBean2.getCount()).isEqualTo(1);
}
@Test
void singletonClientUsePrototype(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ClientBean.class, PrototypeBean.class);
ClientBean clientBean1 = ac.getBean(ClientBean.class);
int count1 = clientBean1.logic();
Assertions.assertThat(count1).isEqualTo(1);
ClientBean clientBean2 = ac.getBean(ClientBean.class);
int count2 = clientBean2.logic();
Assertions.assertThat(count2).isEqualTo(2);
}
@Scope("singleton")
static class ClientBean{
private final PrototypeBean prototypeBean; //생성시점에 주입
@Autowired
public ClientBean(PrototypeBean prototypeBean){
this.prototypeBean = prototypeBean;
}
public int logic(){
prototypeBean.addCount();
int count = prototypeBean.getCount();
return count;
}
}
@Scope("prototype")
static class PrototypeBean {
private int count = 0;
public void addCount(){
count++;
}
public int getCount() {
return count;
}
@PostConstruct
public void init(){
System.out.println("PrototypeBean.init"+this);
}
@PreDestroy
public void destroy(){
System.out.println("PrototypeBean.destroy");
}
}
}
싱글톤 빈은 빌드 시 의존성 주입만 받고 프로토타입 빈은 재구축되지만 싱글톤 빈과 함께 유지되기 때문에 프로토타입 범위의 기능을 사용할 수 없다.