쌓고 쌓다

싱글톤 패턴, 싱글톤 컨테이너(스프링 컨테이너) 본문

프로그래밍/spring

싱글톤 패턴, 싱글톤 컨테이너(스프링 컨테이너)

승민아 2023. 7. 10. 17:43

출처: 인프런 - 김영한

웹 애플리케이션에 클라이언트가 서비스를 요청한다.

스프링이 없는 AppConfig는 그떄마다 객체를 생성하여 응답한다.

아래의 예를 보자.

 

AppConfig

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }
}

 

스프링이 없는 순수 DI 컨테이너

    @Test
    void pureContainer() {
        AppConfig appConfig = new AppConfig();

        // 호출할때마다 객체 생성
        MemberService memberService1 = appConfig.memberService();
        MemberService memberService2 = appConfig.memberService();

        // 참조 값이 다름
        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);

        // ms1 != ms2
        Assertions.assertThat(memberService1).isNotSameAs(memberService2);

        // isSameAs - 객체 인스턴스 == 비교
        // isEqualTo - 자바 equals 메소드
    }

스프링 컨테이너를 사용하지 않고 순수 AppConfig를 통해 MemberService를 요청했다.

각 요청의 응답으로 온 MemberService는 같을까?

인스턴스 출력

각각 다른 인스턴스이다.

 

고객의 요청에 따라 메모리의 낭비가 심하다. 해당 객체를 1개만 생성하여 공유하게하자.

=> 클래스의 인스턴스 1개를 생성하여 공유하는것을 싱글톤 패턴이라고 한다.

 

싱글톤 패턴

  • 생성자를 private으로 만들어 외부에서 인스턴스가 생성되는것을 막자.
  • static으로 객체 instance를 미리 하나 생성해두자.
  • 이 instance는 오직 getInstance() 메소드로만 조회할 수 있다.

 

싱글톤 패턴 적용된 클래스

public class SingletonService {

    // static으로 미리 생성
    private static SingletonService instance = new SingletonService();

    // getInstance() 메소드로만 조회
    public static SingletonService getInstance() {
        return instance;
    }

    // 생성사 private로 외부 생성 불가능 - 싱글톤이구나!
    private SingletonService() {}

    public void logic() {
        System.out.println("싱글톤 객체 로직 호출");
    }

}

 

싱글톤 패턴 클래스 테스트

    @Test
    void singletonServiceTest() {

        SingletonService singletonService1 = SingletonService.getInstance();
        SingletonService singletonService2 = SingletonService.getInstance();

        Assertions.assertThat(singletonService1).isSameAs(singletonService2);
    }

getInstance()로 가져온 객체는 동일한 인스턴스이다.

 

싱글톤 패턴 문제 및 해결

싱글톤 패턴의 문제로 구현 코드가 많이 들어가며 많은 문제들이 있다고하는데 와닿지 않는다.

쨋든 해결 방법으로 스프링 컨테이너가 있다.

 

스프링 컨테이너

스프링 컨테이너가 싱글톤 패턴의 문제점을 해결하며, 객체 인스턴스를 싱글톤(1개만 생성)으로 관리한다.

싱글톤 패턴을 적용하지 않아도 객체 인스턴스를 싱글톤으로 관리해준다!

스프링 빈이 싱글톤으로 관리되는 빈이다.

출처 : 인프런 - 김영한

 

스프링 컨테이너 테스트

    @Test
    void springContainer() {
        ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

        MemberService memberService1 = ac.getBean("memberService", MemberService.class);
        MemberService memberService2 = ac.getBean("memberService", MemberService.class);

        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);

        Assertions.assertThat(memberService1).isSameAs(memberService2);
    }

=> 동일한 인스턴스이다.

 

 

 

 

Comments