본문으로 바로가기
반응형

 

 

시작하기 앞서 싱글톤과 관련된 설명과 코드 예제는 아래 링크에 있다.

 

https://healthdevelop.tistory.com/entry/spring38

 

[Spring] 싱글톤(Singleton) 이란? | 싱글톤 패턴 | 싱글톤 컨테이너 | 웹 애플리케이션과 싱글톤 |Singlet

● 싱글톤 패턴이란?  쉽게 말해 객체 인스턴스가 단 하나만 존재해야 하는 패턴이다. 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생

healthdevelop.tistory.com

 

 

 

 

 

 

 


● 싱글톤 패턴의 문제점

 

 

 

  - 싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다.

 

  - 의존관계상 클라이언트가 구체 클래스에 의존한다.

 

  - DIP를 위반한다.

 

  - 클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다.

 

  - 테스트하기 어렵다.

 

  - 내부 속성을 변경하거나 초기화하기 어렵다.

 

  - private 생성자로 자식 클래스를 만들기 어렵다.

 

  - 결론적으로 유연성이 떨어진다.

 

 

 

 

 

  따라서 싱글톤 패턴안티 패턴으로 부르기도 한다.

 

 

 

 

 

 

 

 


● 싱글톤 컨테이너  

 

 

 

 

 

그러면 위와 같은 싱글톤 패턴의 문제점을 해결할 수는 없는가?

 

 

Spring에서는 싱글톤 컨테이너를 통해 위와 같은 문제점들을 전부 해결해준다.

 

 

 

 

 

스프링 컨테이너싱글턴 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리한다.

컨테이너는 객체를 하나만 생성해서 관리하기 때문이다.

 

 

스프링 컨테이너싱글톤 컨테이너 역할을 한다.

 

 

이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라 한다.

 

 

 

 

스프링 컨테이너의 이런 기능 덕분에 싱글턴 패턴의 모든 단점을 해결하면서

객체를 싱글톤으로 유지할 수 있다.

 

 

 

싱글톤 패턴을 위한 지저분한 코드가 들어가지 않아도 된다.

 

 

DIP, OCP, 테스트, private 생성자로부터 자유롭게 싱글톤을 사용할 수 있다.

 

 

 

 

 

 

 

그럼 스프링 컨테이너를 사용하는 테스트 코드를 작성하여

눈으로 확인해보자.

 

 

 

 

 

 

 

 


● 스프링 컨테이너를 사용하는 테스트 코드

 

 

 

 

SingletonTest.java

 

package hello.core.singleton;

import hello.core.AppConfig;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
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 static org.assertj.core.api.Assertions.*;

public class SingletonTest {

    @Test
    @DisplayName("스프링 컨테이너와 싱글톤")
    void springContainer() {
        // AppConfig appConfig = new AppConfig();
        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);

        // memberService1 == memberService2
        assertThat(memberService1).isSameAs(memberService2);
    }
}

 

AppConfig 클래스를 스프링 컨테이너로 등록한 후,

 

 

memberService를 두 개 생성하고 이 둘의 참조값이 같은지 비교해봤다.

 

 

 

 

 

결과는

 

 

 

 

 

 

 

같은 참조값을 반환하는 것을 볼 수 있다.

 

 

 

 

 

 

 


 

 

 

스프링 컨테이너 덕분에 고객의 요청이 올 때마다 객체를 생성하는 것이 아니라,

이미 만들어진 객체를 공유해서 효율적으로 재사용할 수 있다.

 

 

 

 

참고로 스프링의 기본 빈 등록 방식은 싱글톤이지만, 싱글톤 방식만 지원하는 것은 아니다.

요청할 때 마다 새로운 객체를 생성해서 반환하는 기능도 제공한다.

 

 

자세한 내용은 나중에 빈 스코프에서 설명하겠다

 

 

 

 

 

 

반응형