프로토타입 스코프
싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스 스프링빈을 반환하지만, 프로토타입 스코프를 가진 빈을 조회하면 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.
스프링컨테이너는 빈의 초기화까지만 관리한다. 생성 이후 반환하고부터는 전혀 관리하지않음.
프로토타입 빈을 관리할 책임은 빈을 받은 클라이언트에게 있다.
그래서 @PreDestory같은 종료 메서드는 컨테이너에 의해 자동으로 호출되지 않는다.
싱글톤 테스트
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.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;
import static org.assertj.core.api.Assertions.*;
public class SingletonTest {
@Test
void singletonBeanFind() {
ApplicationContext 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");
}
}
}
테스트 통과했고, 반환받은 객체가 싱글톤임도 확인했다. 컨테이너 close전에 destory()도 정상작동한다.
💡 @Scope(”singletone)은 디폴트 값이라 안붙여도 싱글톤으로 기능하지만, 프로토타입과의 차이를 명확히 보이기 위해 붙였다.
프로토타입 테스트
package hello.core.scope;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import static org.assertj.core.api.Assertions.assertThat;
public class PrototypeScopeTest {
@Test
void prototypeBeanFind() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
System.out.println("find prototypeBean1");
PrototypeBean prototype1 = ac.getBean(PrototypeBean.class);
System.out.println("find prototypeBean2");
PrototypeBean prototype2 = ac.getBean(PrototypeBean.class);
System.out.println("prototype1 = " + prototype1);
System.out.println("prototype2 = " + prototype2);
assertThat(prototype1).isNotSameAs(prototype2);
ac.close();
}
@Scope("prototype")
static class PrototypeBean {
}
@PostConstruct
public void init() {
System.out.println("PrototypeBean.init");
}
@PreDestroy
public void destroy() {
System.out.println("PrototypeBean.destroy");
}
}
다른 객체임을 알 수 있다.
또한 init()까지는 컨테이너가 호출시켜주는 것도 확인할 수 있다.