Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

일상기록

싱글톤 정리 본문

Spring

싱글톤 정리

너 구 나 2023. 4. 13. 17:07

싱글톤 패턴 하나의 객체(bean)만 생성해서 사용하는 디자인 패턴이다.

기존에 일반코드이다. appConfig에서 MemberService를 생성하는 memberService()가 있다.

@Test
    @DisplayName("스프링 없는 순수 DI컨테이너")
    void pureContainer(){
        AppConfig appConfig = new AppConfig();
        MemberService memberService1 = appConfig.memberService();

        MemberService memberService2 = appConfig.memberService();

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

        assertThat(memberService1).isNotSameAs(memberService2);
    }

이렇게 만들었을때 memberService1과 memberService2는 서로다른 참조값을 가진다. 이렇게 구현하게 되면 불필요하게 똑같은 역활을 하는 객체를 하나더 만들어 메모리 효율이 떨어진다.

memberService1과 memberService2 서로다른 참조값

이를 방지하고 디자인 패턴을 적용해서 만들면 아래와 같이 private으로 외부생성을 막고 하나의 자기자신을 가지는 SingletonService를 만든다.

public class SingletonService {
    // 자기자신을 생성해서 가진다 static : 클래스 레벨에서 딱 하나만 가지게 된다.
    private static final SingletonService instance = new SingletonService();

    public  static  SingletonService getInstance(){
        return instance;
    }

    // private 생성자로 외부에서 생성 못하게 막는다.
    private SingletonService(){}

    public void logic(){
        System.out.println("logic() 호출");
    }

이렇게 구현하게 되면 getInstance()메소드로 호출하여 객체를 생성할 수 있게 된다.

싱글톤 패턴을 적용한뒤 singletonService1, 2 참조값을 일치한다.

즉 하나의 객체만 생성해서 사용가능해 진다. 이렇게 Spring Container가 없이 사용할때는 SingletonService.class를 만들어서 사용했다면 Spring Container가 나온이후로는 알아서 싱글톤 패턴을 관리해 준다.

@Test
    @DisplayName("스프링 컨테이너와 싱글톤")
    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);

        assertThat(memberService1).isSameAs(memberService2);
    }

ApplicationContext(Spring Container)가 관리하는 memberService라는 이름을 가진 bean으로 하나의 객체를 memberService1, 2에 각각 넣어줌으로 써 아래와 같은 결과를 볼 수 있다.

TmemberService1, 2의 참조값이 일치한다.

memberService1 위에 [main]으로 보여주는것은 Spring Container에서 관리하고 있는 bean목록 전체를 보여준다.

그 이유는 ApplictaionContext(Spring Container)를 생성함과 동시에 해당 AppConfig.class에 등록된 bean정보를 보여주는 것이다.