인프런 커뮤니티 질문&답변

11 1님의 프로필 이미지
11 1

작성한 질문수

스프링 핵심 원리 - 기본편

싱글톤 방식의 주의점

TestConfig에 @Configuration을 안 붙여도 되는 이유가 이거 맞나요?

해결된 질문

작성

·

462

·

수정됨

0

[질문 템플릿]
1. 강의 내용과 관련된 질문인가요? (예)
2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)
3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)

[질문 내용]

package hello.core.singleton;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

import static org.junit.jupiter.api.Assertions.*;

class StatefulServiceTest {

    @Test
    void statefulServiceSingleton() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
        StatefulService statefulService1 = ac.getBean(StatefulService.class);
        StatefulService statefulService2 = ac.getBean(StatefulService.class);
        // ThreadA: 사용자A 10000원 주문
        int userAPrice = statefulService1.order("userA", 10000);
        // ThreadB: 사용자B 20000원 주문
        int userBPrice = statefulService2.order("userB", 20000);

        // ThreadA: 사용자A 주문 금액 조회
        // int price = statefulService1.getPrice();
        System.out.println("price = " + userAPrice);
        System.out.println(statefulService1);
        System.out.println(statefulService2);
        // Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000);
    }

    static class TestConfig {
        @Bean
        public StatefulService statefulService() {
            return new StatefulService();
        }
    }

}

 

원래 코드에서

        System.out.println(statefulService1);
        System.out.println(statefulService2);

 

이 부분만 제가 추가했습니다. TestConfig에 @Configuration이 없으면, 컨테이너 내부에 등록되는 빈들이 싱글톤을 보장하지 않는다고 알고 있습니다. 그런데 이 코드를 실행한 결과, statefulService1과 statefulService2가 같은 객체라고 나왔습니다. 저는 당연히 다른 객체일 줄 알았거든요. TestConfig에 @Configuration이 없으면 싱글톤을 보장하지 않는다고 알고 있기 때문에..

 

이게 왜 그런지 헷갈렸는데 제가 고민해 본 후의 결론은 다음과 같은데, 오류가 있는지 확인해 주시면 감사드립니다.

 

  1. ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class); 이 코드를 실행하면 TestConfig가 빈으로 등록되지만, TestConfig 내부에 @Bean으로 된 statefulService() 메서드로 반환되는 객체는 싱글톤을 보장하지 않는다.

  2. 하지만 이 코드에선 statefulService()가 한 번밖에 호출되지 않았기 때문에 컨테이너 내부에 생성된 StatefulService 빈이 하나뿐이다.

  3. ac.getBean(StatefulService.class); 이 코드를 여러 번 실행하여 statefulService1, statefulService2, statefulService3 여러 개를 만든다고 해도, 컨테이너 내부의 하나의 객체를 조회한다.

이렇게 생각했는데 혹시 잘못된 부분이 있는지 궁금합니다. 즉, 이 코드는 싱글톤을 보장하지 않는 게 맞지만, 내부에 생성된 객체 자체가 1개뿐이고 더 생성된 것이 없기 때문에, 같은 것을 계속 조회했을 뿐이므로 아래 코드를 실행하면 같은 객체를 출력하게 된다.

        System.out.println(statefulService1);
        System.out.println(statefulService2);

 

틀린 부분이 있다면 지적해 주시면 감사드립니다.

답변 1

3

안녕하세요. 11 1님, 공식 서포터즈 OMG입니다.

1~3번 내용을 보았을 때 이해하신 내용에 틀린 부분은 없는 것 같습니다.

 

statefulService은 자신의 스프링 빈으로 등록되는 시점에만 생성이 이뤄지고, 다른 빈과의 의존관계가 없어서 별도의 추가 생성이 발생하지 않아 하나의 빈이 재사용(호출)되어 같은 객체만을 출력하고 있는게 맞습니다.

 

감사합니다.

11 1님의 프로필 이미지
11 1
질문자

궁금했던 점이 확실히 해소되었습니다. 감사합니다!

11 1님의 프로필 이미지
11 1

작성한 질문수

질문하기