프로토타입 스코프에 대해서 공부해보았다.

 

먼저 기본으로 만들면 싱글톤 스코프가 적용된다.

싱글톤 스코프의 빈을 조회하면 스프링 컨테이너는 항상 같은 인스턴스의 스프링 빈을 반환하는 것이 보장된다.

반면에 프로토타입 스코프를 조회하면 스프링 컨테이너는 항상 새로운 인스턴스를 생성하여 반환한다.

 

싱글톤 빈 요청

1. 싱글톤 스코프의 빈을 스프링 컨테이너에 요청

2. 스프링 컨테이너는 본인이 관리하는 스프링 빈을 반환

3. 이후에 스프링 컨테이너에 같은 요청이 와도 같은 객체 인스턴스의 스프링 빈을 반환.

 

프로토타입 빈 요청

1. 프로토타입 스코프의 빈을 스프링 컨테이너에 요청.

2. 스프링 컨테이너는 이 시점에 프로토타입 빈을 생성하고 필요한 의존관계를 주입.

3. 스프링 컨테이너는 생성한 프로토 타입 빈을 클라이언트에 반환.

4. 스프링 컨테이너에 같은 요청이 오면 항상 새로운 프로토타입 빈을 생성해서 반환.

 

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

클라리언트에 빈을 반환하고 이후 스프링 컨테이너는 생성된 프로토 타입 빈을 관리를 하지 않음

클라이언트가 종료 메서드를 호출해야함. 관리할 책임은 클라이언트가 가지는 것.

 

package hello.core.scope;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class SingletonTest {

    @Test
    void singletonBeanFind(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class);

        SingletonBean bean1 = ac.getBean(SingletonBean.class);
        SingletonBean bean2 = ac.getBean(SingletonBean.class);
        System.out.println("bean1 = " + bean1);
        System.out.println("bean2 = " + bean2);
        Assertions.assertThat(bean1).isSameAs(bean2);
        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");
        }
    }

}

기존에 방식 그대로 싱글톤으로 적용하고 테스트 코드를 작성해보았다.

 

예상했던 결과를 얻을 수 있었다.

 

package hello.core.scope;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Scope;

import javax.annotation.PostConstruct;
import javax.annotation.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);
        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");
        }
    }
}

프로토타입을 이용한 테스트코드를 작성해보았다.

bean1 , bean2 조회시 다르다는 것을 검증하기 위한 코드이다.

 

콘솔을보면

 

- 싱글톤 빈은 스프링 컨테이너 생성 시점에 초기화 메서드가 실행 되지만, 프로토타입 스코프의 빈은

   스프링 컨테이너에서 빈을 조회할 때 생성되고, 초기화 메서드도 실행된다. 

 

- 프로토 타입 빈을 2번 조회하였으므로 다른 빈이 생성되고, 초기화도 2번 실행 된 것을 알 수 있다.

 

- 프로토 타입 빈은 스프링 컨테이너가 생성, 의존관계 주입, 초기화 까지만 관여하고 더는 관리하지 않는다. 따라서

   종료될때 @PreDestroy 같은 종료 메서드가 전혀 실행되지 않는다.

 

 

+ Recent posts