프로토타입 스코프

학습 페이지

싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스 스프링빈을 반환하지만, 프로토타입 스코프를 가진 빈을 조회하면 컨테이너는 항상 새로운 인스턴스를 생성해서 반환한다.

프로토타입 빈 요청시

Untitled

Untitled

스프링컨테이너는 빈의 초기화까지만 관리한다. 생성 이후 반환하고부터는 전혀 관리하지않음.

프로토타입 빈을 관리할 책임은 빈을 받은 클라이언트에게 있다.

그래서 @PreDestory같은 종료 메서드는 컨테이너에 의해 자동으로 호출되지 않는다.

  1. 싱글톤 테스트

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

Untitled

테스트 통과했고, 반환받은 객체가 싱글톤임도 확인했다. 컨테이너 close전에 destory()도 정상작동한다.

💡 @Scope(”singletone)은 디폴트 값이라 안붙여도 싱글톤으로 기능하지만, 프로토타입과의 차이를 명확히 보이기 위해 붙였다.

  1. 프로토타입 테스트

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

    Untitled

다른 객체임을 알 수 있다.

또한 init()까지는 컨테이너가 호출시켜주는 것도 확인할 수 있다.