-
빈 스코프(Singleton, Prototype)개발/Spring 2023. 5. 16. 17:07
https://literate-t.tistory.com/405 내용에서 조금 더 보완하고자 한다.
@Configuration
테스트 코드를 작성하는데, 클래스에 @Configuration을 붙이지 않아도 getBean 메서드로 빈이 획득됐다. 관련 내용을 찾아 보니 공식 문서에 꽤나 친절하게 설명이 있었다. https://docs.spring.io/spring-framewo
literate-t.tistory.com
위 포스트의 내용은 @Bean 어노테이션을 이용해 빈으로 등록된 객체에 관한 문제다.
클래스에 @Configuration 어노테이션을 붙이면 빈은 정식 스프링 빈이 되어 싱글톤으로 관리되고,
붙이지 않으면 싱글톤으로 관리되지 않는다. 여기서 관리되지 않는 지점에 대해 부연하자면
B bean이 생성될 때 A bean이 필요하다면 그냥 새로운 A bean이 만들어진다는 의미다.
@Scope("singleton")
이와 별개로 @Bean을 가지고 있는 클래스(@Configuration 어노테이션이 붙는 클래스)는 기본적으로 싱글톤이다.
다음 테스트를 통과한다. SingletonBean의 close 함수도 호출된다.
public class SingletonTest { @Test void findSingletonBean() { ConfigurableApplicationContext context = new AnnotationConfigApplicationContext(SingletonBean.class); SingletonBean singletonBean1 = context.getBean(SingletonBean.class); SingletonBean singletonBean2 = context.getBean(SingletonBean.class); System.out.println("singletonBean1 = " + singletonBean1); System.out.println("singletonBean2 = " + singletonBean2); Assertions.assertThat(singletonBean1).isSameAs(singletonBean2); context.close(); } @Scope("singleton") // default 이므로 안 붙여도 된다 static class SingletonBean { @PostConstruct void init() { System.out.println("SingletonBean.init"); } @PreDestroy void close() { System.out.println("SingletonBean.close"); } } }
AnnotationConfigApplicationContext의 생성자의 파라미터 중 하나는 componentClasses다.
즉, 인수로 넣는 클래스는 @Component를 붙이는 것과 동일한 효과를 가지므로 위의 코드가 동작할 수 있다.
@Scope("prototype")
빈의 스코프를 프로토타입으로 바꾸면 빈 생성 후 DI까지만 진행된다.
그러고 나서 스프링 컨테이너에서 해당 빈들이 반환되어 싱글톤으로 관리되지 않는다.
다음 테스트를 통과하며 close 함수는 각 빈에서 명시적으로 호출하지 않으면 호출되지 않는다.
public class PrototypeTest { @Test void findPrototypeBean() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(PrototypeBean.class); System.out.println("find Prototype Bean1"); PrototypeBean p1 = context.getBean(PrototypeBean.class); System.out.println("find Prototype Bean1"); PrototypeBean p2 = context.getBean(PrototypeBean.class); System.out.println("p1 = " + p1); System.out.println("p2 = " + p2); assertThat(p1).isNotSameAs(p2); // p1.close(); // p2.close(); context.close(); } @Scope("prototype") static class PrototypeBean { @PostConstruct void init() { System.out.println("PrototypeBean.init"); } @PreDestroy void close() { System.out.println("PrototypeBean.close"); } } }
'개발 > Spring' 카테고리의 다른 글
세션 인증 때 커스텀 애노테이션 적용하기 (0) 2023.06.26 Validation에서 에러 문구 설정 (0) 2023.06.20 컨트롤러(핸들러)가 조회되는 과정 (2) 2023.06.11 @Configuration (0) 2023.05.10 [AOP] before의 우선순위 (0) 2023.04.30