코드 그라데이션

프로토타입 스코프 본문

Spring/핵심 원리 구현

프로토타입 스코프

완벽한 장면 2024. 2. 14. 01:34

프로토타입 스코프

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

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

 

 

싱글톤 빈 요청

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

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

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

 

 


프로토타입 빈 요청 1

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

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

 

 

프로토타입 빈 요청2

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

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

 

 

정리

 


코드로 확인해보면

싱글톤 스코프 빈 테스트

package inflearn.spring_core.scope;

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;

import static org.assertj.core.api.Assertions.assertThat;

public class SingletonTest {

    @Test
    public void singletonBeanFind() {
        // SingletonBean 클래스 구성을 기반으로 스프링 애플리케이션 컨텍스트를 생성합니다.
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonBean.class);

        // 스프링 컨테이너에서 SingletonBean의 두 인스턴스를 가져옵니다.
        SingletonBean singletonBean1 = ac.getBean(SingletonBean.class);
        SingletonBean singletonBean2 = ac.getBean(SingletonBean.class);

        // singletonBean1과 singletonBean2의 참조를 출력합니다.
        System.out.println("singletonBean1 = " + singletonBean1);
        System.out.println("singletonBean2 = " + singletonBean2);

        // 두 참조가 동일한 객체를 가리키는지 확인하여 싱글톤 범위를 확인합니다.
        assertThat(singletonBean1).isSameAs(singletonBean2);

        // 스프링 애플리케이션 컨텍스트를 닫습니다. 이로써 PreDestroy 메서드가 호출됩니다.
        ac.close(); // 종료 (컨텍스트 종료)
    }

    @Scope("singleton")
    static class SingletonBean {

        // @PostConstruct로 주석이 달린 메서드는 빈 초기화 이후에 호출됩니다.
        @PostConstruct
        public void init() {
            System.out.println("SingletonBean.init");
        }

        // @PreDestroy로 주석이 달린 메서드는 빈 파괴 이전에 호출됩니다.
        @PreDestroy
        public void destroy() {
            System.out.println("SingletonBean.destroy");
        }
    }
    
}

 

실행 결과

  • 빈 초기화 메서드를 실행하고,
  • 같은 인스턴스의 빈을 조회하고,
  • 종료 메서드까지 정상 호출 된 것을 확인할 수 있다.

 

 

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

package inflearn.spring_core.scope;

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;

import static org.assertj.core.api.Assertions.assertThat;

public class PrototypeTest {

    @Test
    public void prototypeBeanFind() {
        // 프로토타입 빈을 사용하는 스프링 애플리케이션 컨텍스트를 생성합니다.
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
        System.out.println("프로토타입 빈 1 찾기");

        // 스프링 컨테이너에서 PrototypeBean의 첫 번째 인스턴스를 가져옵니다.
        PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
        System.out.println("프로토타입 빈 2 찾기");

        // 스프링 컨테이너에서 PrototypeBean의 두 번째 인스턴스를 가져옵니다.
        PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);
        System.out.println("prototypeBean1 = " + prototypeBean1);
        System.out.println("prototypeBean2 = " + prototypeBean2);

        // 두 참조가 서로 다른 객체를 가리키는지 확인하여 프로토타입 범위를 확인합니다.
        assertThat(prototypeBean1).isNotSameAs(prototypeBean2);

        // 스프링 애플리케이션 컨텍스트를 닫습니다. 이로써 PreDestroy 메서드가 호출됩니다.
        ac.close(); // 종료
    }
    

    @Scope("prototype")
    static class PrototypeBean {

        // @PostConstruct로 주석이 달린 메서드는 빈 초기화 이후에 호출됩니다.
        @PostConstruct
        public void init() {
            System.out.println("PrototypeBean.init");
        }

        // @PreDestroy로 주석이 달린 메서드는 빈 파괴 이전에 호출됩니다.
        @PreDestroy
        public void destroy() {
            System.out.println("PrototypeBean.destroy");
        }
    }
}

 

부연

 

실행 결과

 

 

프로토타입 빈의 특징 정리

  • 스프링 컨테이너에 요청할 때 마다 새로 생성된다.
  • 스프링 컨테이너는 프로토타입 빈의 생성과 의존관계 주입 그리고 초기화까지만 관여한다.
  • 종료 메서드가 호출되지 않는다.
  • 그래서 프로토타입 빈은 프로토타입 빈을 조회한 클라이언트가 관리해야 한다.                                                              종료 메서드에 대한 호출도 클라이언트가 직접 해야한다.

 

728x90
Comments