↩뒤로가기

웹 애플리케이션과 싱글톤

Untitled

스프링이 적용되지 않은 순수한 DI 컨테이너

@Test
    @DisplayName("스프링 없는 순수한 DI 컨테이너")
    void pureContainer(){
        AppConfig appConfig = new AppConfig();
        //1. 조회: 호출할 때 마다 객체를 생성
        MemberService memberService1 = appConfig.memberService();

        //2. 조회: 호출할 때 마다 객체를 생성
        MemberService memberService2 = appConfig.memberService();

        //참조값이 다른 것을 확인
        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);
//        memberService1 = hello.core.member.MemberServiceImpl@24269709
//        memberService2 = hello.core.member.MemberServiceImpl@2aceadd4

        //memberService1 != memberService2
        assertThat(memberService1).isNotSameAs(memberService2);
    }

이와 같이, 스프링 빈 컨테이너를 사용하지 않는 DI는 요청할 때마다 새로운 객체를 생성한다.

싱글톤 패턴

싱글톤 패턴을 만드는 방법

package hello.core.singleton;

public class SingletonService {
		//클래스 내에 미리 객체를 생성해두기
    private static final SingletonService instatnce = new SingletonService();

/*
"private static final"은 이 변수를 클래스 내부에서만 접근 가능하며, 값이 변경되지 않음
"SingletonService instance" 변수에 "new SingletonService()"를 할당하여 이 클래스의 유일한 인스턴스를 생성
new SingletonService(); 불가능
*/

		//외부에서 객체를 호출할 방법 정의
    public static SingletonService getInstance(){
        return instatnce;
    }
/*
객체를 불러올 수 있는 유일한 방법은 메소드의 리턴값으로 보내는 것이다.
이 메서드를 호출하면 최초에 생성된 인스턴스를 반복적으로 반환한다.
*/

		//객체 추가 생성 방지
    private SingletonService(){
    }
//private 접근제한자로 인해 외부에서 new SingletonService() 로 객체를 생성할 수 없다.

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

}

<aside> 💡 "static"은 자바 프로그래밍에서 사용되는 키워드로, 클래스의 공유 멤버를 의미한다. 정적 멤버(static member)는 클래스 이름을 통해 접근할 수 있으며, 클래스의 인스턴스를 생성하지 않고도 사용할 수 있다. 즉, 클래스의 모든 인스턴스가 공유하는 변수와 메서드를 표현할 때 사용할 수 있다.

예를 들어, 클래스에서 static 변수를 선언하면, 클래스의 모든 인스턴스가 같은 값을 가지는 공유 변수가 된다. 메서드에 static 선언 시 클래스의 모든 인스턴스가 공유하는 메서드를 표현할 때 사용할 수 있다.

결론적으로, static은 클래스의 공유 멤버를 의미하며, 클래스의 모든 인스턴스가 공유하는 변수와 메서드를 표현할 때 사용한다.

</aside>

검증하기

@Test
    @DisplayName("싱글톤 패턴을 적용한 객체 사용")
    void singletonServiceTest(){
        SingletonService singletonService1 = SingletonService.getInstance();
				//싱글톤 클래스에서 미리 만들어둔 객체를 호출한다.
        SingletonService singletonService2 = SingletonService.getInstance();
				//한번 더 호출해서 다른 변수에 할당한다.

        System.out.println("singletonService1 = " + singletonService1);
        System.out.println("singletonService2 = " + singletonService2);
        
        assertThat(singletonService1).isSameAs(singletonService2);
    }