[Spring] 9-2. 프로토타입 스코프

송광호·2024년 1월 18일

[Spring]

목록 보기
38/41
post-thumbnail

Spring 시리즈는 혼자 공부하며 기록으로 남기고, 만약 잘못 학습 한 지식이 있다면 공유하며 피드백을 받고자 작성합니다.
스프링에 대해 깊게 공부해보고자 인프런의 김영한 강사님께서 강의를 진행하시는 (스프링 핵심 원리 - 기본편) 강의를 수강하며 정리하는 글입니다.
혹여나 글을 읽으시며 잘못 설명된 부분이 있다면 지적 부탁드리겠습니다.


싱글톤 빈 스코프

  • 우선 그동안 해왔던 싱글톤 스코프 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환한다.
  • 반면에 프로토타입 스코프는 스프링 컨테이너에서 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다. (생성, 의존관계 주입, 초기화만 해주고 반환)

싱글톤 빈 요청

    1. 싱글톤 스코프의 빈을 컨테이너에 요청을 하면
    1. 스프링 컨테이너는 본인이 이미 관리하던 스프링 빈을 반환한다.
    1. 이후에 스프링 컨테이너에 같은 요청이 와도 같은 객체 인스턴스의 스프링 빈을 반환한다.

싱글톤 테스트 코드

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);
        Assertions.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@3591009c
singletonBean2 = hello.core.scope.SingletonTest$SingletonBean@3591009c
19:27:07.315 [Test worker] DEBUG o.s.c.a.AnnotationConfigApplicationContext -- Closing
SingletonBean.destroy
  • 생성 메서드와 소멸 메서드까지 정상적으로 호출 된 것을 확인할 수 있다.

프로토타입 빈 스코프

프로토타입 빈 요청

    1. 클라이언트가 프로토타입 스코프 빈을 스프링 컨테이너에 달라고 요청하면
    1. 그때 프로토타입 빈을 생성하고, 필요한 의존관계를 주입한다.

    1. 스프링 컨테이너는 생성된 프로토타입 빈을 초기화까지 하고나서 반환하고 더이상 관리하지 않는다.
    1. 이후에 클라이언트가 같은 요청을 하면 항상 새로운 프로토타입 빈을 생성해서 반환한다.

살짝콩 정리

  • 계속 언급했지만 스프링 컨테이너는 프로토타입 빈을 생성하고, 의존관계를 주입하고, 초기화까지만 처리한다.
  • 반환하고 나서는 프로토타입 빈을 관리할 책임은 클라이언트에게 있다.
  • 클라이언트가 따로 종료 메서드를 호출하지 않으면 @PreDestroy같은 종료 메서드는 호출되지 않는다.

프로토타입 테스트 코드

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);

        //prototypeBean1.destroy();
        //prototypeBean2.destroy();

        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");
        }
    }
}
  • 위에서 정리한 내용대로라면 요청을 할 때마다 새로운 인스턴스를 생성하고, @PreDestroy 애노테이션이 붙은 메서드는 호출이 될 리가 없다.

프로토타입 테스트 결과

find prototypeBean1
PrototypeBean.init
find prototypeBean2
PrototypeBean.init
prototypeBean1 = hello.core.scope.PrototypeTest$PrototypeBean@3591009c
prototypeBean2 = hello.core.scope.PrototypeTest$PrototypeBean@5398edd0
19:35:17.475 [Test worker] DEBUG o.s.c.a.AnnotationConfigApplicationContext -- Closing
  • 서로 다른 객체 인스턴스가 생성되는걸 확인할 수 있다.
  • 그리고 소멸메서드 또한 호출되지 않는다.
  • 소멸메서드를 사용하고싶으면 따로 .destroy() 코드를 작성해야한다.

프로토타입 빈 특징 정리

  • 스프링 컨테이너에 요청할 때마다 새로 생성된다.
  • 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입 그리고 초기화까지만 관여하고 더이상 신경쓰지 않는다.
  • 그래서 종료메서드가 호출되지 않는 것 이다.
  • 관여가 끝나면 프로토타입 빈의 관리는 클라이언트가 해야한다.

0개의 댓글