빈 스코프

인프런 스프링 핵심 원리 - 기본편 수강 중

빈 스코프란?

빈이 생성되어 종료되는 라이프사이클 범위

스프링 지원 스코프

  • 싱글톤:
    기본 스코프, 스프링 컨테이너의 시작부터 종료까지 유지되는 가장 넓은 범위 스코프로 여태까지는 모두 싱글톤 스코프
  • 프로토타입:
    스프링 컨테이너가 프로토타입의 빈 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위 스코프
  • 웹 관련 스코프:
    • request 스코프:
      웹 요청이 들어오고 나갈때까지 유지되는 스코프
    • session 스코프:
      웹 세션이 생성되고 종료될 때까지 유지되는 스코프
    • application 스코프:
      웹의 서블릿 컨텍스와 같은 범위로 유지되는 스코프

스코프 선언

컴포넌트 스캔 자동 등록

@Scope("prototype")
@Component
public class HelloBean {}

컴포넌트 스캔 수동 등록

@Scope("prototype")
@Bean
PrototypeBean HelloBean() {
  return new HelloBean();
}

스코프 동작

싱글톤 빈 요청

그림1

  1. 스프링 컨테이너에 싱글톤 스코프 빈 요청
  2. 스프링 컨테이너가 관리하는 스프링 빈 반환
  3. 같은 요청이 와도 같은 객체 인스턴스 스프링 빈 반환

그림2

  1. 스프링 컨테이너에 프로토타입 스코프 빈 요청
  2. 요청시 스프링 컨테익너가 프로토타입 빈 생성 및 필요 의존관계 주입

그림3

  1. 스프링 컨테이너는 생성한 프로토타입 빈 반환
  2. 이후 같은 요청이 와도 항상 새로운 프로토타입 빈 생성 및 반환

스프링 컨테이너는 프로토타입 빈을 생성, 의존관계 주입, 초기화까지만 처리

싱글톤 빈 스코프 테스트

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");
        }
    }
}
  • 스프링 컨테이너 생성 시점에 빈 초기화 메서드 실행
  • 같은 인스턴스 빈 조회
  • 종료 메서드 호출

프로토타입 빈 스코프 테스트

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 destroy(){
            System.out.println("PrototypeBean.destroy");
        }
    }
}
  • 스프링 컨테이너에서 빈을 조회할 때 생성되고 초기화 메서드 실행
  • 프로토타입 빈을 2번 조회하여 다른 스프링 빈 생성
  • 스프링 컨테이너가 생성, 의존관계 주입, 초기화까지만 관여하기 때문에 스프링 컨테이너 종료시 @PreDestroy 같은 종료 메서드 실행하지 않음 ➡️필요시 직접 호출해야 함

[참조] 인프런 스프링 핵심 원리 - 기본편 - 링크

끝!