노션으로 다시 돌아갔습니다 😅

[빈 스코프] 빈 스코프와 프로토타입 스코프

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

활동하기